R Notebook
#Introduction We chose to focus on rich people, or people presumably
with high-income jobs, throughout our project. People are generally
really interested in the lives of rich people, and this is really
appealing to readers, which makes it newsworthy. We noticed this
specifically this week in the Wall Street Journal where many of the
front page articles pertained to the inside lives of wealthier people,
for example investment bankers and more.
For example, in our question about what people are contributing to
with their specific jobs, we focused on CEO’s who presumably make a good
living. We then looked at that across Democratic and Republican parties
to note the differences between these two groups in terms of the same
occupation.
#Process and Question Development Do more Marylanders donate to
in-state or out-of-state candidates? Which out-of-state candidates
received the most donations and the greatest amount of money in
donations? What are the demographics of people who donate to Maryland
races only? To out-of-state races only? (using voter data OR using
census data to see if those donors are clustered in specific locations,
and, if they are, what the makeups of those locations are) Among top
Maryland donors, what professions donate the most money to senate
campaigns? What’s the makeup of donations received by Hogan and
Alsobrooks? What percentage of their overall donations were large
amounts of money (to be defined, but > $1000, for example) vs small
amounts? Which party tends to donate more to out-of-state races?
We refined our dataset further by deciding to focus on individual
donations made to senate races by donors in Maryland. Using the FEC
website, we downloaded a dataset that met those parameters. We cleaned
the data by removing unnecessary columns and renaming the columns where
needed. We decided to limit our dataset to donations made in 2024 to
ensure that the donations were made after the primary and before the
general election. We hoped this would limit the number of candidates
receiving donations, since most donations will go toward one of two
parties in a certain race.
We also cleaned the data-set, removing numerous columns that were N/A
or that were unnecessary to our project. We also had to rename one
column and then filter to only the report year of 2024 to limit the
donations. To answer our first question and questions, we’ll need to
separate the out-of-state candidates from in-state candidates, but this
should be easy because we’ll just need to filter out the Hogan and
Alsobrooks committees to isolate the out-of-state candidates receiving
donations. To answer our third question, we’ll need to either call in
demographic data from the census or identify specific locations with
clusters of donations, and look up information about those locations
using census.gov. Question #4 asks about the professions of donors. One
obvious challenge here is that professions and titles are often spelled
or worded differently, even if they describe the same job– in this
dataset, there are 2,738 different professions listed. To try to combat
this, we will use open refine to reduce the number of occupations with
slight variations in spelling or wording. We will then limit the data
set to the top 1000 donations to make the analysis more manageable. We
can also make some broad observations about the data even without
cleaning the professions– for example, it’s obvious that the most
donations come from people who say they are “not employed” (45568) or
“retired” (29424). The next highest number of donations is more than
20,000 donations less than the number of donations from retired people.
There are 207 committees that received donations in our dataset.
Originally, we thought that we would use open refine to sort the
committees by candidate name, because we thought that most candidates
would have multiple committees. However, we found that this was actually
pretty uncommon, and we weren’t able to match any names using open
refine, once we uploaded our csv. For question 5, we need to do some
extra research to decide how to define large donations. One idea is to
find the average or median donation, and use that number as the dividing
line between small and large donations. Another idea is to see if
there’s an agreed-upon definition by people who work on campaigns or
political scientists. We have one extra question (#6) that we would like
to answer, but it involves party-level analysis that we can’t do because
we don’t have the political parties of the donors in this data, and we
don’t have anything in this data that indicates the party of each
candidate. To answer this question, we could join this data with data
from Act Blue and Win Red to identify the parties of donors. We can also
probably find a dataset with the committee names and parties for all
senate candidates, and join that dataset with ours.
#Refining the dataset
options(scipen=999)
library(tidyverse)
library(lubridate)
library(dplyr)
install.packages('tidycensus')
There is a binary version available but the source version is later:
installing the source package ‘tidycensus’
trying URL 'https://cran.rstudio.com/src/contrib/tidycensus_1.6.7.tar.gz'
Content type 'application/x-gzip' length 2262396 bytes (2.2 MB)
==================================================
downloaded 2.2 MB
* installing *source* package ‘tidycensus’ ...
** package ‘tidycensus’ successfully unpacked and MD5 sums checked
** using staged installation
** R
** data
*** moving datasets to lazyload DB
* removing ‘/Library/Frameworks/R.framework/Versions/4.2/Resources/library/tidycensus’
* restoring previous ‘/Library/Frameworks/R.framework/Versions/4.2/Resources/library/tidycensus’
Warning in install.packages :
installation of package ‘tidycensus’ had non-zero exit status
The downloaded source packages are in
‘/private/var/folders/2l/xcvc2w597t9714c985cwdbr40000gp/T/RtmpfQuLsL/downloaded_packages’
library(tidycensus)
md_senate_contributions <- read_csv("data/md_senate_contributions.csv") |>
print(column_names)
New names:Warning: One or more parsing issues, call `problems()` on your data frame for details, e.g.:
dat <- vroom(...)
problems(dat)Rows: 115275 Columns: 79── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (44): committee_id, committee_name...2, report_type, line_number, transaction_id, entity_type, entity_type_desc, unused_contbr_id, ...
dbl (11): report_year, image_number, file_number, contributor_zip, contribution_receipt_amount, contributor_aggregate_ytd, conduit_comm...
lgl (22): committee_name...9, recipient_committee_org_type, memo_code_full, candidate_id, candidate_name, candidate_first_name, candida...
dttm (2): contribution_receipt_date, load_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
clean data:
cleaned_data <- md_senate_contributions |>
select( -unused_contbr_id, -committee_name...9, -recipient_committee_org_type, -contributor_suffix, -contributor_street_2, -contributor_id, -memo_code, -memo_code_full, -candidate_id, -candidate_name, -candidate_first_name, -candidate_last_name, -candidate_middle_name, -candidate_prefix, -candidate_suffix, -candidate_office, -candidate_office_full, -candidate_office_state, -candidate_office_state_full, -candidate_office_district, -conduit_committee_id, -conduit_committee_name, -conduit_committee_street1, -conduit_committee_street2, -conduit_committee_city, -conduit_committee_state, -conduit_committee_zip, -donor_committee_name, -national_committee_nonfederal_account, -election_type_full, -increased_limit, -is_individual) |>
rename(committee_name = `committee_name...2`) |>
filter(report_year == 2024)
colnames(cleaned_data)
[1] "committee_id" "committee_name" "report_year" "report_type"
[5] "image_number" "line_number" "transaction_id" "file_number"
[9] "entity_type" "entity_type_desc" "contributor_prefix" "contributor_name"
[13] "recipient_committee_type" "recipient_committee_designation" "contributor_first_name" "contributor_middle_name"
[17] "contributor_last_name" "contributor_street_1" "contributor_city" "contributor_state"
[21] "contributor_zip" "contributor_employer" "contributor_occupation" "receipt_type"
[25] "receipt_type_desc" "receipt_type_full" "contribution_receipt_date" "contribution_receipt_amount"
[29] "contributor_aggregate_ytd" "election_type" "fec_election_type_desc" "fec_election_year"
[33] "amendment_indicator" "amendment_indicator_desc" "schedule_type_full" "load_date"
[37] "original_sub_id" "back_reference_transaction_id" "back_reference_schedule_name" "filing_form"
[41] "link_id" "memo_text" "two_year_transaction_period" "schedule_type"
[45] "sub_id" "pdf_url" "line_number_label"
most_contributions <- cleaned_data |>
select(committee_name, contribution_receipt_amount) |>
group_by(committee_name) |>
summarize(total_contribution = sum(contribution_receipt_amount, na.rm = TRUE)) |>
arrange(desc(total_contribution))
cleaned_data |>
write_csv("data/cleaned_md_senate_contributions.csv")
data <- read_delim("data/ccl.txt", delim = "|", col_names = FALSE)
Rows: 8568 Columns: 7── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "|"
chr (4): X1, X4, X5, X6
dbl (3): X2, X3, X7
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
cleaned_data_ccl <- data |>
rename(candidate_id = X1,candidate_election_year = X2, fec_election_year = X3, committee_id = X4,committee_type = X5,committee_design = X6, linkage_id = X7)
inner join the committee id and fec election year:
joined_data <- inner_join(cleaned_data, cleaned_data_ccl, by = c("committee_id", "fec_election_year"))
Warning: Detected an unexpected many-to-many relationship between `x` and `y`.
insert the candidate data:
candidate_data <- read_delim("data/candidate_data.txt", delim = "|", col_names = FALSE) |>
select(X1, X2, X3, X5) |>
rename(candidate_id = X1, candidate_name = X2, candidate_party = X5)
Rows: 3824 Columns: 30── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "|"
chr (7): X1, X2, X3, X5, X19, X20, X28
dbl (18): X4, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X26, X27, X29, X30
lgl (5): X21, X22, X23, X24, X25
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
candidate_joined_data <- inner_join(joined_data, candidate_data, by =c("candidate_id"))
include only these rows:
final_data <- candidate_joined_data |>
select(committee_id, committee_name, report_year, entity_type_desc,contributor_prefix, contributor_name, contributor_first_name, contributor_last_name, contributor_middle_name, contributor_street_1,contributor_city, contributor_state, contributor_zip,contributor_employer, contributor_occupation, contribution_receipt_date, contribution_receipt_amount, contributor_aggregate_ytd,memo_text,pdf_url, candidate_id, candidate_election_year)
#Question 1: Do more Marylanders donate to in-state or out-of-state
candidates?
final_data_states <- final_data |>
mutate(state = substr(candidate_id, 3, 4))
state_contributions <- final_data_states |>
group_by(state) |>
summarise(
contribution_count = n(),
total_contribution = sum(contribution_receipt_amount, na.rm = TRUE)
)
maryland_contrib <- state_contributions |>
filter(state == "MD") |>
summarise(total_maryland_contrib = sum(total_contribution, na.rm = TRUE))
other_states_contrib <- state_contributions |>
filter(state != "MD") |>
summarise(total_other_states_contrib = sum(total_contribution, na.rm = TRUE))
comparison <- data.frame(
state = c("Maryland", "Other States"),
total_contribution = c(maryland_contrib$total_maryland_contrib, other_states_contrib$total_other_states_contrib)
)
#Answer 1: Montana was surprisingly the state with the most
contributions — edging Maryland with 202 more contributions Maryland.
Maryland received the highest total sum however, with $5,516,562.24.
That was $4,074,226.07 more than the next highest state, which was
Montana. The other states combined recieved $7,358,970, a little less
than two million more than just the state of Maryland.
#Question 2: Which out-of-state candidates received the most
donations and the greatest amount of money in donations?
final_data_no_md <- final_data_states |>
filter(state != "MD")
contributions_summary <- final_data_no_md |>
group_by(committee_name) |>
summarise(
num_contributions = n(),
total_contribution_sum = sum(contribution_receipt_amount, na.rm = TRUE)
) |>
arrange(committee_name)
#Answer 2: Jon Tester, Sherrod Brown and Ruben Gallego were the top
three in that order for both contributions recieved and the sum of
contributions. The similarity between the three of them is that they
were all Democrats running in tightly contested races. Brown was the
only to lose his race. Jon Tester also clearly recieved more than the
other two — which explains why Montana received so many more
out-of-state contributions than other states. Montanans for Tester
received 3,679 more contributions and $238,017.96 more in total
contributions compared to Friends of Sherrod Brown.
We chose not to focus on refining and coding this question. Looking
at donations to candidates like Tester and Alsobrooks would not answer
our newsworthiness because our focus is on where wealthy individuals’
money goes in elections. While it is interesting that out-of-state
donations align with competitive Senate races, such as Montana and Ohio,
this analysis would primarily highlight geographic donation trends
rather than the behavior of high-income donors. Our story aims to
display how wealthy individuals, particularly CEOs, use their financial
power in election donations. Examining specific candidates or
out-of-state donations would not provide the same insight into the role
of wealth and leadership positions in shaping overall donation patterns,
which makes our findings newsworthy.
However, the other questions we explored provided were more relevant.
By focusing on CEOs, we were able to show patterns of financial
influence resonating with public interest. People are often more curious
about how wealthy individuals spend their money, especially in the
context of elections, and we felt that the other questions we explored
provided more relevant insights that aligned with our potential news
story about where wealthy individuals’ money goes in elections.
#Question 3: What are the demographics of people who donate to
Maryland races only? To out-of-state races only?
Step 1: find people who donate to ONLY Maryland races.
maryland_only_donors <- final_data_states|>
group_by(contributor_name) |>
summarize(only_md = all(state == "MD")) |>
filter(only_md) |>
select(contributor_name)
full_maryland_only_donors <- final_data_states |>
filter(contributor_name %in% maryland_only_donors$contributor_name)
zips_full_maryland_only_donors <- full_maryland_only_donors |>
group_by(contributor_name, contributor_zip) |>
summarize(
num_donations = n(),
total_donated = sum(contribution_receipt_amount)
)|>
arrange(desc(num_donations))
`summarise()` has grouped output by 'contributor_name'. You can override using the `.groups` argument.
md_zip_summary <- zips_full_maryland_only_donors |>
group_by(contributor_zip) |>
summarize(
num_donations = n(),
total_donated = sum(total_donated)
) |>
arrange(desc(num_donations))
all_zcta <- get_acs(
geography = "zcta",
variables = c(
"B01003_001",
"B01002_001", #= "median_age",
"B19013_001", # = "median_income",
"B02001_002", # = "white_alone",
"B02001_003", # = "black_alone",
"B02001_004", # = "native_american",
"B02001_005", #= "asian_alone",
"B02001_006", # = "hawaiian_pacific",
"B02001_007", # = "other_race",
"B02001_008", # = "two_or_more_races"
"B03002_012E"),
year = 2022,
survey = "acs5",
output = "wide"
)
Getting data from the 2018-2022 5-year ACS
all_zcta <- all_zcta %>%
rename(
total_population = B01003_001E,
median_age = B01002_001E,
median_income = B19013_001E,
white_alone = B02001_002E,
black_alone = B02001_003E,
native_american = B02001_004E,
asian_alone = B02001_005E,
hawaiian_pacific = B02001_006E,
other_race = B02001_007E,
two_or_more_races = B02001_008E,
hispanic_or_latino = B03002_012E
)
zips_full_maryland_only_donors <- zips_full_maryland_only_donors |>
mutate(
contributor_zip = substr(contributor_zip, 1, 5),
contributor_zip = sprintf("%05s", contributor_zip)
)
zips_full_maryland_only_donors <- zips_full_maryland_only_donors |>
mutate(contributor_zip = as.character(contributor_zip))
merged_data_md <- zips_full_maryland_only_donors %>%
left_join(all_zcta, by = c("contributor_zip" = "GEOID"))
summarized_md_donor_demos_by_zip <- merged_data_md %>%
group_by(contributor_zip) |>
summarize(
total_population = first(total_population),
median_age = first(median_age),
median_income = first(median_income),
white_alone = first(white_alone),
black_alone = first(black_alone),
native_american = first(native_american),
asian_alone = first(asian_alone),
hawaiian_pacific = first(hawaiian_pacific),
other_race = first(other_race),
hispanic_or_latino = first(hispanic_or_latino),
two_or_more_races = first(two_or_more_races),
num_donations = n(),
total_amt_donated = sum(total_donated, na.rm = TRUE)
) |>
arrange(desc(num_donations)) |>
mutate(
white_alone_per_capita = white_alone / total_population,
black_alone_per_capita = black_alone / total_population,
native_american_per_capita = native_american / total_population,
asian_alone_per_capita = asian_alone / total_population,
hawaiian_pacific_per_capita = hawaiian_pacific / total_population,
other_race_per_capita = other_race / total_population,
hispanic_or_latino_per_capita = hispanic_or_latino / total_population,
two_or_more_races_per_capita = two_or_more_races / total_population,
median_income_per_capita = median_income / total_population
) |>
mutate(
white_alone_percent = white_alone_per_capita * 100,
black_alone_percent = black_alone_per_capita * 100,
native_american_percent = native_american_per_capita * 100,
asian_alone_percent = asian_alone_per_capita * 100,
hawaiian_pacific_percent = hawaiian_pacific_per_capita * 100,
other_race_percent = other_race_per_capita * 100,
hispanic_or_latino_percent = hispanic_or_latino_per_capita *100,
two_or_more_races_percent = two_or_more_races_per_capita * 100,
median_income_per_capita = median_income_per_capita * 100
) |>
mutate(
amt_donated_per_resident = total_amt_donated / total_population
) |>
select(where(~ !all(is.na(.))))
cleaner_md_donor_demos <- summarized_md_donor_demos_by_zip |>
select(-matches("_per_capita"), -"native_american", -"hawaiian_pacific", -"other_race", -"two_or_more_races", -"white_alone", -"black_alone", -"asian_alone")
repeat for out of state donors:
out_of_state_donors <- final_data_states |>
filter(state != "MD")
xmaryland_donors <- final_data_states |>
filter(state == "MD")
out_of_state_only_donors <- out_of_state_donors |>
filter(!contributor_name %in% xmaryland_donors$contributor_name) |>
group_by(contributor_name, contributor_zip) |>
summarize(
num_donations = n(),
total_donated = sum(contribution_receipt_amount)
) |>
arrange(desc(num_donations))
`summarise()` has grouped output by 'contributor_name'. You can override using the `.groups` argument.
out_of_state_only_donors <- out_of_state_only_donors |>
mutate(
contributor_zip = substr(contributor_zip, 1, 5),
contributor_zip = sprintf("%05s", contributor_zip)
)
merged_data_oos <- out_of_state_only_donors|>
left_join(all_zcta, by = c("contributor_zip" = "GEOID"))
cleaner_oos_donor_demos <- merged_data_oos |>
group_by(contributor_zip) |>
summarize(
total_population = first(total_population),
median_age = first(median_age),
median_income = first(median_income),
white_alone = first(white_alone),
black_alone = first(black_alone),
native_american = first(native_american),
asian_alone = first(asian_alone),
hawaiian_pacific = first(hawaiian_pacific),
other_race = first(other_race),
hispanic_or_latino = first(hispanic_or_latino),
two_or_more_races = first(two_or_more_races),
num_donations = n(),
total_amt_donated = sum(total_donated, na.rm = TRUE)
) |>
arrange(desc(num_donations)) |>
mutate(
white_alone_per_capita = white_alone / total_population,
black_alone_per_capita = black_alone / total_population,
native_american_per_capita = native_american / total_population,
asian_alone_per_capita = asian_alone / total_population,
hawaiian_pacific_per_capita = hawaiian_pacific / total_population,
other_race_per_capita = other_race / total_population,
hispanic_or_latino_per_capita = hispanic_or_latino / total_population,
two_or_more_races_per_capita = two_or_more_races / total_population,
median_income_per_capita = median_income / total_population
) |>
mutate(
white_alone_percent = white_alone_per_capita * 100,
black_alone_percent = black_alone_per_capita * 100,
native_american_percent = native_american_per_capita * 100,
asian_alone_percent = asian_alone_per_capita * 100,
hawaiian_pacific_percent = hawaiian_pacific_per_capita * 100,
other_race_percent = other_race_per_capita * 100,
hispanic_or_latino_percent = hispanic_or_latino_per_capita *100,
two_or_more_races_percent = two_or_more_races_per_capita * 100,
median_income_per_capita = median_income_per_capita * 100
)
cleaner_oos_donor_demos <- cleaner_oos_donor_demos |> select(-matches("_per_capita"), -"native_american", -"hawaiian_pacific", -"other_race", -"two_or_more_races", -"white_alone", -"black_alone", -"asian_alone") |>
mutate(
amt_donated_per_resident = total_amt_donated / total_population
) |>
select(where(~ !all(is.na(.))))
head(merged_data_oos)
cleaner_oos_donor_demos <- cleaner_oos_donor_demos |>
mutate(
contributor_zip = as.character(contributor_zip), # Ensure ZIP codes are strings
contributor_zip = str_pad(contributor_zip, width = 5, # Pad with leading zeros to ensure 5 digits
side = "left", pad = "0"),
contributor_zip = ifelse(str_detect(contributor_zip, "^\\d{5}$"), # Keep only valid 5-digit ZIP codes
contributor_zip, NA)) |>
mutate(contributor_zip = ifelse(contributor_zip == "30639", "20639", contributor_zip))
cleaner_oos_donor_demos |> arrange(desc(amt_donated_per_resident)) |> write_csv("cleaner_oos_donor_demos.csv")
cleaner_md_donor_demos <- cleaner_md_donor_demos |>
mutate(
contributor_zip = as.character(contributor_zip), # Ensure ZIP codes are strings
contributor_zip = str_pad(contributor_zip, width = 5, # Pad with leading zeros to ensure 5 digits
side = "left", pad = "0"),
contributor_zip = ifelse(str_detect(contributor_zip, "^\\d{5}$"), # Keep only valid 5-digit ZIP codes
contributor_zip, NA))
cleaner_md_donor_demos|> arrange(desc(amt_donated_per_resident)) |> write_csv("cleaner_md_donor_demos.csv")
top_cleaner_md_donor_demos <- cleaner_md_donor_demos |>
arrange(desc(amt_donated_per_resident)) |>
filter(contributor_zip != "21287") |>
slice_head(n = 5)
write_csv(top_cleaner_md_donor_demos, "top_cleaner_md_donor_demos.csv")
top_cleaner_oos_donor_demos <- cleaner_oos_donor_demos |>
arrange(desc(amt_donated_per_resident)) |>
slice_head(n = 5)
write_csv(top_cleaner_oos_donor_demos, "top_cleaner_oos_donor_demos.csv")
cleaner_oos_donor_demos <- cleaner_oos_donor_demos |>
arrange(desc(amt_donated_per_resident))
cleaner_md_donor_demos <- cleaner_md_donor_demos |>
arrange(desc(amt_donated_per_resident))
#Creating table comparing demographics of donors to in-state and out-of-state elections.
oos_averages <- cleaner_oos_donor_demos |>
mutate(across(where(is.numeric), ~ ifelse(is.infinite(.), NA, .))) |>
summarize(
white_pct = mean(white_alone_percent, na.rm = TRUE),
black_pct = mean(black_alone_percent, na.rm = TRUE),
native_american_pct = mean(native_american_percent, na.rm = TRUE),
asian_pct = mean(asian_alone_percent, na.rm = TRUE),
hawaiian_pacific_pct = mean(hawaiian_pacific_percent, na.rm = TRUE),
other_race_pct = mean(other_race_percent, na.rm = TRUE),
hispanic_or_latino_pct = mean(hispanic_or_latino_percent, na.rm = TRUE),
two_or_more_races_pct = mean(two_or_more_races_percent, na.rm = TRUE),
amt_donated_per_resident = mean(amt_donated_per_resident, na.rm = TRUE),
median_age = median(median_age,na.rm = TRUE),
median_income = median(median_income, na.rm = TRUE),
total_num_donations = sum(num_donations, na.rm = TRUE),
total_amt_donations = sum(total_amt_donated, na.rm = TRUE),
race_donated = c("out_of_state")) |>
select(race_donated, everything()) |>
mutate(across(where(is.numeric), ~ round(. , 2))) |>
write_csv("oos_averages.csv")
md_averages <- cleaner_md_donor_demos |>
summarize(
white_pct = mean(white_alone_percent, na.rm = TRUE),
black_pct = mean(black_alone_percent, na.rm = TRUE),
native_american_pct = mean(native_american_percent, na.rm = TRUE),
asian_pct = mean(asian_alone_percent, na.rm = TRUE),
hawaiian_pacific_pct = mean(hawaiian_pacific_percent, na.rm = TRUE),
other_race_pct = mean(other_race_percent, na.rm = TRUE),
hispanic_or_latino_pct = mean(hispanic_or_latino_percent, na.rm = TRUE),
two_or_more_races_pct = mean(two_or_more_races_percent, na.rm = TRUE),
amt_donated_per_resident = mean(amt_donated_per_resident, na.rm = TRUE),
median_age = median(median_age,na.rm = TRUE),
median_income = median(median_income, na.rm = TRUE),
total_num_donations = sum(num_donations, na.rm = TRUE),
total_amt_donations = sum(total_amt_donated, na.rm = TRUE),
race_donated = c("maryland")) |>
select(race_donated, everything()) |>
mutate(across(where(is.numeric), ~ round(. , 2))) |>
write_csv("md_averages.csv")
combined_averages <- bind_rows(oos_averages, md_averages)|>
write_csv("combined_averages.csv")
Datawrapper table: https://datawrapper.dwcdn.net/nc5uT/1/
#Answer 3:
In asking and answering this question, we attempt to use donations as
a measure of a donor’s perception of their donation’s ability to impact
the outcome of a race, meaning that people who donated only to
Maryland’s senate race, we infer, determined that their donation would
be most impactful to that race. Conversely, people who donated
only to out-of-state races determined that their donations were
most needed to influence those races.
It is certainly possible that donors give money to candidates for
other reasons (Maybe they’re just a big fan of a certain politican).
However, given that the top out-of-state donations were made to
candidates in competitive races, and that Maryland’s senate race was
competitive this year, we think this is a reasonable theory that we can
use to interpret this data.
To illustrate our findings, I first created two Datawrapper maps
showing donation amount per capita and demographic data, including
median income and age, and racial makeup.
In-state election donors: https://datawrapper.dwcdn.net/91uYI/1/ Out-of-state
election donors: https://datawrapper.dwcdn.net/PllQC/1/
From comparing those maps, it’s clear that Marylanders in certain
parts of the state (the wealthy DC suburbs, Annapolis, and parts of
Talbot county) donate more money, whether they are donating to in-state
or out-of-state elections.
We can see that for Maryland races, donors in those high-donation
areas donated similar amounts per capita. However, for out-of-state
races, the largest donations per capita were concentrated around the DC
suburbs.
This is likely because Maryland’s wealthiest donors live in that part
of the state, and made large donations to candidates Jon Tester, Sherrod
Brown and Ruben Gallego in an effort to sway competitive races in swing
states.
Donations to Maryland races were more evenly dispersed across the
state. This may be because the Maryland race was competitive this year,
and Marylanders felt that their contributions to the in-state senate
race could make a difference in shaping the outcome of the election (as
opposed to more typical election years, where Maryland is an uncontested
blue state).
I also found that, comparing the demographics of the two groups
against each other, they were remarkable similar in every factor that I
measured. This might imply that demographics like race, income, or age
did not influence a donor’s liklihood to donate in-state vs
out-of-state.
I created this table with my findings: https://datawrapper.dwcdn.net/nc5uT/1/
Question 4: Among top Maryland donors, what professions donate the
most money to senate campaigns?
individual_donors <- final_data_states|>
group_by(contributor_name, contributor_zip, contributor_occupation, contributor_employer) |>
summarize(
num_donations = n(),
total_donated = sum(contribution_receipt_amount)
) |>
arrange(desc(num_donations))
jobs_to_clean <- individual_donors |>
group_by(contributor_occupation) |>
summarize(
number_jobs = n(),
num_donations = n(),
total_donations = sum(total_donated)
) |> arrange(desc(number_jobs)) |>
write_csv("data/jobs_to_clean.csv")
boss_to_clean <- individual_donors |>
group_by(contributor_employer) |>
summarize(
number_jobs = n(),
num_donations = n(),
total_donations = sum(total_donated)
) |> arrange(desc(number_jobs)) |>
write_csv("data/boss_to_clean.csv")
clean_employer <- read_csv("data/cleaned_boss.csv")
clean_occupation <- read_csv("data/clean_jobs.csv")
clean_occupation |>
group_by(cleaned_jjobs) |>
summarize(
number_jobs = n(),
num_donations = n(),
total_donated = sum(total_donations)) |>
arrange(cleaned_jjobs)
clean_occupation <- read_csv("data/clean_jobs.csv")
clean_occupation <- clean_occupation |>
mutate(cleaned_jjobs = case_when(
contributor_occupation %in% c("C.E.O.", "CEO", "CEO & FOUNDER", "CEO & MEDIA CONTRIBUTOR",
"CEO & PRESIDENT", "CEO UNDERWRITING", "CEO/AUTHOR",
"CHAIRMAN, CEO AND PRESIDENT", "CHIEF EXECUTIVE OFFICER",
"CO-CEO", "CO-FOUNDER & CEO", "PRESIDENT & CEO",
"FOUNDER CEO", "PRESIDENT & C.E.O.", "PRESIDENT / CEO",
"PRESIDENT CEO") ~ "CEO",
contributor_occupation %in% c("DEPUTY", "DEPUTY ADMINISTRATOR & DIRECTOR",
"DEPUTY ASSISTANT SECRETARY", "DEPUTY CHIEF ADMINISTRATIVE OFFICER",
"DEPUTY COS", "DEPUTY DIRECTOR", "DEPUTY RESEARCH DIRECTOR",
"DEPUTY SECRETARY", "DEPUTY SECRETARY OF COMMERCE") ~ "DEPUTY",
TRUE ~ contributor_occupation
))
overall_totals <- clean_occupation |>
summarize(
total_jobs = sum(number_jobs, na.rm = TRUE),
total_donations = sum(total_donations, na.rm = TRUE)
)
ceo_deputy_proportions <- clean_occupation |>
filter(cleaned_jjobs %in% c("CEO", "DEPUTY")) |>
group_by(cleaned_jjobs) |>
summarize(
total_number_jobs = sum(number_jobs, na.rm = TRUE),
total_num_donations = sum(num_donations, na.rm = TRUE),
total_donations = sum(total_donations, na.rm = TRUE)
) |>
mutate(
prop_number_jobs = round((total_number_jobs / overall_totals$total_jobs) * 100, 2),
prop_total_donations = round((total_donations / overall_totals$total_donations) * 100, 2)
)
ceo_deputy_proportions
#Answer 4:
To answer this question, we put a csv of occupations into OpenRefine.
We originally planned to limit the data set, but we found that there
were only 1,963 job titles in the data set, which seemed like a
reasonable number to refine down into a smaller list of jobs.
To do this, we grouped certain jobs into categories like “director”
and “executive” – so job titles like “sales director” went into the
“director” category.
We chose to focus on CEOS and began by pulling and merging all of the
same terms for CEO. There were 20 of them. We then decided to compare
that to deputies, which was extremely interesting to us because they are
government employees. According to research, they are allowed to donate.
We merged all of the names with deputy together. Then we created a new
dataset with DEPUTY and CEO, but the numbers are disporportionate, so we
made them proportinate as follows: prop_number_jobs Proportion of jobs
in the dataset for each category, relative to the total number of jobs.
prop_num_donations Proportion of the number of donations made, relative
to the total donations count. prop_total_donations Proportion of the
total dollar value donated, relative to the total donation amount.
Our analysis showed that CEOs make up only 1.88% of all jobs in the
dataset, but they account for 3.59% of the total donations. This means
that while there aren’t many CEOs compared to other job titles, they
donate a lot more money, which reflects their financial influence.
On the other hand, DEPUTYs,many of whom are government employees,
make up 0.08% of all jobs and contribute only 0.05% of total donations.
This is a much smaller presence compared to CEOs and shows that public
sector employees like DEPUTYs donate far less overall.
This is important because it highlights a clear difference between
private-sector leadership roles and government positions when it comes
to donations. CEOs, who often earn high salaries, seem to have much more
financial power to make donations. DEPUTYs, in contrast, contribute far
less, which might reflect differences in income or rules about political
giving for public employees.
What stands out is that donations aren’t spread evenly across job
types—most of the money comes from a small group of people in leadership
positions. This raises interesting questions about income, influence,
and how donations shape things like political campaigns or charitable
efforts.
This is newsworthy because it highlights how a small group of
high-income CEOs disproportionately drives donations, revealing economic
disparities and the outsized financial influence of private-sector
leaders.
#Question 5: What’s the makeup of donations received by Hogan and
Alsobrooks? What percentage of their overall donations were large
amounts of money (to be defined, but > $1000, for example) vs small
amounts?
hogan_filtered_data <- final_data |>
filter(committee_name %in% c("HOGAN FOR MARYLAND INC."))
large_donation_threshold <- 1000
hogan_filtered_data |> mutate( donation_category = ifelse(contribution_receipt_amount > large_donation_threshold, "Large", "Small") )
hogan_category_totals <- hogan_filtered_data |>
mutate(donation_category = ifelse(contribution_receipt_amount > large_donation_threshold, "Large", "Small")) |>
group_by(donation_category) |>
summarise(total_amount = sum(contribution_receipt_amount, na.rm = TRUE), .groups = "drop")
hogan_category_totals %>% mutate( percentage = total_amount / sum(total_amount) * 100 )
hogan_category_totals
alsobrooks_filtered_data <- final_data |>
filter(committee_name %in% c("ALSOBROOKS FOR SENATE"))
large_donation_threshold <- 1000
alsobrooks_category_totals <- alsobrooks_filtered_data |>
mutate(donation_category = ifelse(contribution_receipt_amount > large_donation_threshold, "Large", "Small")) |>
group_by(donation_category) |>
summarise(total_amount = sum(contribution_receipt_amount, na.rm = TRUE), .groups = "drop")
alsobrooks_category_totals %>% mutate( percentage = total_amount / sum(total_amount) * 100 )
alsobrooks_category_totals
hogan_filtered_data <- hogan_filtered_data |>
mutate(contributor_zip = substr(as.character(contributor_zip), 1, 5))
hogan_zips <- hogan_filtered_data |>
group_by(contributor_zip) |>
summarise(count = n())
write_csv(hogan_zips, "hogan_zips.csv")
alsobrooks_filtered_data <- alsobrooks_filtered_data |>
mutate(contributor_zip = substr(as.character(contributor_zip), 1, 5))
alsobrooks_zips <- alsobrooks_filtered_data |>
group_by(contributor_zip) |>
summarise(count = n())
write_csv(alsobrooks_zips, "alsobrooks_zips.csv")
hogan_large_data <- hogan_filtered_data |>
mutate(contributor_zip = substr(as.character(contributor_zip), 1, 5)) |>
filter(contribution_receipt_amount > 1000) |>
group_by(contributor_zip) |>
summarise(count = n())
write_csv(hogan_large_data, "hogan_large.csv")
alsobrooks_large_data <- alsobrooks_filtered_data |>
mutate(contributor_zip = substr(as.character(contributor_zip), 1, 5)) |>
filter(contribution_receipt_amount > 1000) |>
group_by(contributor_zip) |>
summarise(count = n())
write_csv(alsobrooks_large_data, "alsobrooks_large.csv")
A5: Here we see that Hogan receives signficantly more money in
general in comparison to Alsobrooks. Additionally, Hogan receives many
more large donations (in excess of millions) in comparison to
Alsobrooks. Whereas, the small donations are around 600,000 more. This
shows that either Hogan has a larger “fan base” of people who donate to
him or perhaps his electorate is just wealthier. Additionally,it would
be interesting to note whether Hogan has a higher amount of donations
because he was known before.
We then looked at where these donations were from. For Hogan, his
most donations came from Annapolis — his former residence and where the
state legislature is located. His second most donations came from
Potomac, the zip code with the highest median household income in
Maryland. However, 14 different zip codes donated more to Alsobrooks
than Annapolis did for Hogan. This showed Hogan thrived off of large
donations in areas that Alsobrooks did reach.
We tested this using chloropleth maps to show the zip codes where the
two received large donations. The map showed a lot of areas in northern
Maryland he capitalized with those donations where Alsobrooks did not
recieve any.
There were a few zip codes which did not register on DataWrapper when
making these graphs, but they did not have more than five donations, so
we did not think that it ultimately affected determining where the hot
areas were for the two receiving their donations.
Map of Larry Hogan’s donations by zipcode: https://www.datawrapper.de/_/5LB3T/
Map of Angela Alsobrooks’ donations by zipcode: https://www.datawrapper.de/_/ChtAr/
Map of Angela Alsobrooks’ large donations by zipcode: https://www.datawrapper.de/_/BEuvY/
Map of Larry Hogan’s large donations by zipcode: https://www.datawrapper.de/_/6KTF3/
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKUiBOb3RlYm9vawoKI0ludHJvZHVjdGlvbgpXZSBjaG9zZSB0byBmb2N1cyBvbiByaWNoIHBlb3BsZSwgb3IgcGVvcGxlIHByZXN1bWFibHkgd2l0aCBoaWdoLWluY29tZSBqb2JzLCB0aHJvdWdob3V0IG91ciBwcm9qZWN0LiBQZW9wbGUgYXJlIGdlbmVyYWxseSByZWFsbHkgaW50ZXJlc3RlZCBpbiB0aGUgbGl2ZXMgb2YgcmljaCBwZW9wbGUsIGFuZCB0aGlzIGlzIHJlYWxseSBhcHBlYWxpbmcgdG8gcmVhZGVycywgd2hpY2ggbWFrZXMgaXQgbmV3c3dvcnRoeS4gV2Ugbm90aWNlZCB0aGlzIHNwZWNpZmljYWxseSB0aGlzIHdlZWsgaW4gdGhlIFdhbGwgU3RyZWV0IEpvdXJuYWwgd2hlcmUgbWFueSBvZiB0aGUgZnJvbnQgcGFnZSBhcnRpY2xlcyBwZXJ0YWluZWQgdG8gdGhlIGluc2lkZSBsaXZlcyBvZiB3ZWFsdGhpZXIgcGVvcGxlLCBmb3IgZXhhbXBsZSBpbnZlc3RtZW50IGJhbmtlcnMgYW5kIG1vcmUuIAoKRm9yIGV4YW1wbGUsIGluIG91ciBxdWVzdGlvbiBhYm91dCB3aGF0IHBlb3BsZSBhcmUgY29udHJpYnV0aW5nIHRvIHdpdGggdGhlaXIgc3BlY2lmaWMgam9icywgd2UgZm9jdXNlZCBvbiBDRU8ncyB3aG8gcHJlc3VtYWJseSBtYWtlIGEgZ29vZCBsaXZpbmcuIFdlIHRoZW4gbG9va2VkIGF0IHRoYXQgYWNyb3NzIERlbW9jcmF0aWMgYW5kIFJlcHVibGljYW4gcGFydGllcyB0byBub3RlIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZXNlIHR3byBncm91cHMgaW4gdGVybXMgb2YgdGhlIHNhbWUgb2NjdXBhdGlvbi4gCgojUHJvY2VzcyBhbmQgUXVlc3Rpb24gRGV2ZWxvcG1lbnQKRG8gbW9yZSBNYXJ5bGFuZGVycyBkb25hdGUgdG8gaW4tc3RhdGUgb3Igb3V0LW9mLXN0YXRlIGNhbmRpZGF0ZXM/IFdoaWNoIG91dC1vZi1zdGF0ZSBjYW5kaWRhdGVzIHJlY2VpdmVkIHRoZSBtb3N0IGRvbmF0aW9ucyBhbmQgdGhlIGdyZWF0ZXN0IGFtb3VudCBvZiBtb25leSBpbiBkb25hdGlvbnM/IFdoYXQgYXJlIHRoZSBkZW1vZ3JhcGhpY3Mgb2YgcGVvcGxlIHdobyBkb25hdGUgdG8gTWFyeWxhbmQgcmFjZXMgb25seT8gVG8gb3V0LW9mLXN0YXRlIHJhY2VzIG9ubHk/ICh1c2luZyB2b3RlciBkYXRhIE9SIHVzaW5nIGNlbnN1cyBkYXRhIHRvIHNlZSBpZiB0aG9zZSBkb25vcnMgYXJlIGNsdXN0ZXJlZCBpbiBzcGVjaWZpYyBsb2NhdGlvbnMsIGFuZCwgaWYgdGhleSBhcmUsIHdoYXQgdGhlIG1ha2V1cHMgb2YgdGhvc2UgbG9jYXRpb25zIGFyZSkgQW1vbmcgdG9wIE1hcnlsYW5kIGRvbm9ycywgd2hhdCBwcm9mZXNzaW9ucyBkb25hdGUgdGhlIG1vc3QgbW9uZXkgdG8gc2VuYXRlIGNhbXBhaWducz8gV2hhdOKAmXMgdGhlIG1ha2V1cCBvZiBkb25hdGlvbnMgcmVjZWl2ZWQgYnkgSG9nYW4gYW5kIEFsc29icm9va3M/IFdoYXQgcGVyY2VudGFnZSBvZiB0aGVpciBvdmVyYWxsIGRvbmF0aW9ucyB3ZXJlIGxhcmdlIGFtb3VudHMgb2YgbW9uZXkgKHRvIGJlIGRlZmluZWQsIGJ1dCA+ICQxMDAwLCBmb3IgZXhhbXBsZSkgdnMgc21hbGwgYW1vdW50cz8gV2hpY2ggcGFydHkgdGVuZHMgdG8gZG9uYXRlIG1vcmUgdG8gb3V0LW9mLXN0YXRlIHJhY2VzPwoKV2UgcmVmaW5lZCBvdXIgZGF0YXNldCBmdXJ0aGVyIGJ5IGRlY2lkaW5nIHRvIGZvY3VzIG9uIGluZGl2aWR1YWwgZG9uYXRpb25zIG1hZGUgdG8gc2VuYXRlIHJhY2VzIGJ5IGRvbm9ycyBpbiBNYXJ5bGFuZC4gVXNpbmcgdGhlIEZFQyB3ZWJzaXRlLCB3ZSBkb3dubG9hZGVkIGEgZGF0YXNldCB0aGF0IG1ldCB0aG9zZSBwYXJhbWV0ZXJzLiBXZSBjbGVhbmVkIHRoZSBkYXRhIGJ5IHJlbW92aW5nIHVubmVjZXNzYXJ5IGNvbHVtbnMgYW5kIHJlbmFtaW5nIHRoZSBjb2x1bW5zIHdoZXJlIG5lZWRlZC4gV2UgZGVjaWRlZCB0byBsaW1pdCBvdXIgZGF0YXNldCB0byBkb25hdGlvbnMgbWFkZSBpbiAyMDI0IHRvIGVuc3VyZSB0aGF0IHRoZSBkb25hdGlvbnMgd2VyZSBtYWRlIGFmdGVyIHRoZSBwcmltYXJ5IGFuZCBiZWZvcmUgdGhlIGdlbmVyYWwgZWxlY3Rpb24uIFdlIGhvcGVkIHRoaXMgd291bGQgbGltaXQgdGhlIG51bWJlciBvZiBjYW5kaWRhdGVzIHJlY2VpdmluZyBkb25hdGlvbnMsIHNpbmNlIG1vc3QgZG9uYXRpb25zIHdpbGwgZ28gdG93YXJkIG9uZSBvZiB0d28gcGFydGllcyBpbiBhIGNlcnRhaW4gcmFjZS4KCldlIGFsc28gY2xlYW5lZCB0aGUgZGF0YS1zZXQsIHJlbW92aW5nIG51bWVyb3VzIGNvbHVtbnMgdGhhdCB3ZXJlIE4vQSBvciB0aGF0IHdlcmUgdW5uZWNlc3NhcnkgdG8gb3VyIHByb2plY3QuIFdlIGFsc28gaGFkIHRvIHJlbmFtZSBvbmUgY29sdW1uIGFuZCB0aGVuIGZpbHRlciB0byBvbmx5IHRoZSByZXBvcnQgeWVhciBvZiAyMDI0IHRvIGxpbWl0IHRoZSBkb25hdGlvbnMuIFRvIGFuc3dlciBvdXIgZmlyc3QgcXVlc3Rpb24gYW5kIHF1ZXN0aW9ucywgd2XigJlsbCBuZWVkIHRvIHNlcGFyYXRlIHRoZSBvdXQtb2Ytc3RhdGUgY2FuZGlkYXRlcyBmcm9tIGluLXN0YXRlIGNhbmRpZGF0ZXMsIGJ1dCB0aGlzIHNob3VsZCBiZSBlYXN5IGJlY2F1c2Ugd2XigJlsbCBqdXN0IG5lZWQgdG8gZmlsdGVyIG91dCB0aGUgSG9nYW4gYW5kIEFsc29icm9va3MgY29tbWl0dGVlcyB0byBpc29sYXRlIHRoZSBvdXQtb2Ytc3RhdGUgY2FuZGlkYXRlcyByZWNlaXZpbmcgZG9uYXRpb25zLiBUbyBhbnN3ZXIgb3VyIHRoaXJkIHF1ZXN0aW9uLCB3ZeKAmWxsIG5lZWQgdG8gZWl0aGVyIGNhbGwgaW4gZGVtb2dyYXBoaWMgZGF0YSBmcm9tIHRoZSBjZW5zdXMgb3IgaWRlbnRpZnkgc3BlY2lmaWMgbG9jYXRpb25zIHdpdGggY2x1c3RlcnMgb2YgZG9uYXRpb25zLCBhbmQgbG9vayB1cCBpbmZvcm1hdGlvbiBhYm91dCB0aG9zZSBsb2NhdGlvbnMgdXNpbmcgY2Vuc3VzLmdvdi4gUXVlc3Rpb24gIzQgYXNrcyBhYm91dCB0aGUgcHJvZmVzc2lvbnMgb2YgZG9ub3JzLiBPbmUgb2J2aW91cyBjaGFsbGVuZ2UgaGVyZSBpcyB0aGF0IHByb2Zlc3Npb25zIGFuZCB0aXRsZXMgYXJlIG9mdGVuIHNwZWxsZWQgb3Igd29yZGVkIGRpZmZlcmVudGx5LCBldmVuIGlmIHRoZXkgZGVzY3JpYmUgdGhlIHNhbWUgam9i4oCTIGluIHRoaXMgZGF0YXNldCwgdGhlcmUgYXJlIDIsNzM4IGRpZmZlcmVudCBwcm9mZXNzaW9ucyBsaXN0ZWQuIFRvIHRyeSB0byBjb21iYXQgdGhpcywgd2Ugd2lsbCB1c2Ugb3BlbiByZWZpbmUgdG8gcmVkdWNlIHRoZSBudW1iZXIgb2Ygb2NjdXBhdGlvbnMgd2l0aCBzbGlnaHQgdmFyaWF0aW9ucyBpbiBzcGVsbGluZyBvciB3b3JkaW5nLiBXZSB3aWxsIHRoZW4gbGltaXQgdGhlIGRhdGEgc2V0IHRvIHRoZSB0b3AgMTAwMCBkb25hdGlvbnMgdG8gbWFrZSB0aGUgYW5hbHlzaXMgbW9yZSBtYW5hZ2VhYmxlLiBXZSBjYW4gYWxzbyBtYWtlIHNvbWUgYnJvYWQgb2JzZXJ2YXRpb25zIGFib3V0IHRoZSBkYXRhIGV2ZW4gd2l0aG91dCBjbGVhbmluZyB0aGUgcHJvZmVzc2lvbnPigJMgZm9yIGV4YW1wbGUsIGl04oCZcyBvYnZpb3VzIHRoYXQgdGhlIG1vc3QgZG9uYXRpb25zIGNvbWUgZnJvbSBwZW9wbGUgd2hvIHNheSB0aGV5IGFyZSDigJxub3QgZW1wbG95ZWTigJ0gKDQ1NTY4KSBvciDigJxyZXRpcmVk4oCdICgyOTQyNCkuIFRoZSBuZXh0IGhpZ2hlc3QgbnVtYmVyIG9mIGRvbmF0aW9ucyBpcyBtb3JlIHRoYW4gMjAsMDAwIGRvbmF0aW9ucyBsZXNzIHRoYW4gdGhlIG51bWJlciBvZiBkb25hdGlvbnMgZnJvbSByZXRpcmVkIHBlb3BsZS4gVGhlcmUgYXJlIDIwNyBjb21taXR0ZWVzIHRoYXQgcmVjZWl2ZWQgZG9uYXRpb25zIGluIG91ciBkYXRhc2V0LiBPcmlnaW5hbGx5LCB3ZSB0aG91Z2h0IHRoYXQgd2Ugd291bGQgdXNlIG9wZW4gcmVmaW5lIHRvIHNvcnQgdGhlIGNvbW1pdHRlZXMgYnkgY2FuZGlkYXRlIG5hbWUsIGJlY2F1c2Ugd2UgdGhvdWdodCB0aGF0IG1vc3QgY2FuZGlkYXRlcyB3b3VsZCBoYXZlIG11bHRpcGxlIGNvbW1pdHRlZXMuIEhvd2V2ZXIsIHdlIGZvdW5kIHRoYXQgdGhpcyB3YXMgYWN0dWFsbHkgcHJldHR5IHVuY29tbW9uLCBhbmQgd2Ugd2VyZW7igJl0IGFibGUgdG8gbWF0Y2ggYW55IG5hbWVzIHVzaW5nIG9wZW4gcmVmaW5lLCBvbmNlIHdlIHVwbG9hZGVkIG91ciBjc3YuIEZvciBxdWVzdGlvbiA1LCB3ZSBuZWVkIHRvIGRvIHNvbWUgZXh0cmEgcmVzZWFyY2ggdG8gZGVjaWRlIGhvdyB0byBkZWZpbmUgbGFyZ2UgZG9uYXRpb25zLiBPbmUgaWRlYSBpcyB0byBmaW5kIHRoZSBhdmVyYWdlIG9yIG1lZGlhbiBkb25hdGlvbiwgYW5kIHVzZSB0aGF0IG51bWJlciBhcyB0aGUgZGl2aWRpbmcgbGluZSBiZXR3ZWVuIHNtYWxsIGFuZCBsYXJnZSBkb25hdGlvbnMuIEFub3RoZXIgaWRlYSBpcyB0byBzZWUgaWYgdGhlcmXigJlzIGFuIGFncmVlZC11cG9uIGRlZmluaXRpb24gYnkgcGVvcGxlIHdobyB3b3JrIG9uIGNhbXBhaWducyBvciBwb2xpdGljYWwgc2NpZW50aXN0cy4gV2UgaGF2ZSBvbmUgZXh0cmEgcXVlc3Rpb24gKCM2KSB0aGF0IHdlIHdvdWxkIGxpa2UgdG8gYW5zd2VyLCBidXQgaXQgaW52b2x2ZXMgcGFydHktbGV2ZWwgYW5hbHlzaXMgdGhhdCB3ZSBjYW7igJl0IGRvIGJlY2F1c2Ugd2UgZG9u4oCZdCBoYXZlIHRoZSBwb2xpdGljYWwgcGFydGllcyBvZiB0aGUgZG9ub3JzIGluIHRoaXMgZGF0YSwgYW5kIHdlIGRvbuKAmXQgaGF2ZSBhbnl0aGluZyBpbiB0aGlzIGRhdGEgdGhhdCBpbmRpY2F0ZXMgdGhlIHBhcnR5IG9mIGVhY2ggY2FuZGlkYXRlLiBUbyBhbnN3ZXIgdGhpcyBxdWVzdGlvbiwgd2UgY291bGQgam9pbiB0aGlzIGRhdGEgd2l0aCBkYXRhIGZyb20gQWN0IEJsdWUgYW5kIFdpbiBSZWQgdG8gaWRlbnRpZnkgdGhlIHBhcnRpZXMgb2YgZG9ub3JzLiBXZSBjYW4gYWxzbyBwcm9iYWJseSBmaW5kIGEgZGF0YXNldCB3aXRoIHRoZSBjb21taXR0ZWUgbmFtZXMgYW5kIHBhcnRpZXMgZm9yIGFsbCBzZW5hdGUgY2FuZGlkYXRlcywgYW5kIGpvaW4gdGhhdCBkYXRhc2V0IHdpdGggb3Vycy4KCiNSZWZpbmluZyB0aGUgZGF0YXNldAoKYGBge3J9Cm9wdGlvbnMoc2NpcGVuPTk5OSkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KGRwbHlyKQoKCmBgYAoKYGBge3J9Cmluc3RhbGwucGFja2FnZXMoJ3RpZHljZW5zdXMnKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KHRpZHljZW5zdXMpCmBgYAoKCgpgYGB7cn0KbWRfc2VuYXRlX2NvbnRyaWJ1dGlvbnMgPC0gcmVhZF9jc3YoImRhdGEvbWRfc2VuYXRlX2NvbnRyaWJ1dGlvbnMuY3N2IikgfD4KCgpwcmludChjb2x1bW5fbmFtZXMpCmBgYAoKY2xlYW4gZGF0YToKYGBge3J9CmNsZWFuZWRfZGF0YSA8LSBtZF9zZW5hdGVfY29udHJpYnV0aW9ucyB8PgoKc2VsZWN0KCAtdW51c2VkX2NvbnRicl9pZCwgLWNvbW1pdHRlZV9uYW1lLi4uOSwgLXJlY2lwaWVudF9jb21taXR0ZWVfb3JnX3R5cGUsIC1jb250cmlidXRvcl9zdWZmaXgsIC1jb250cmlidXRvcl9zdHJlZXRfMiwgLWNvbnRyaWJ1dG9yX2lkLCAtbWVtb19jb2RlLCAtbWVtb19jb2RlX2Z1bGwsIC1jYW5kaWRhdGVfaWQsIC1jYW5kaWRhdGVfbmFtZSwgLWNhbmRpZGF0ZV9maXJzdF9uYW1lLCAtY2FuZGlkYXRlX2xhc3RfbmFtZSwgLWNhbmRpZGF0ZV9taWRkbGVfbmFtZSwgLWNhbmRpZGF0ZV9wcmVmaXgsIC1jYW5kaWRhdGVfc3VmZml4LCAtY2FuZGlkYXRlX29mZmljZSwgLWNhbmRpZGF0ZV9vZmZpY2VfZnVsbCwgLWNhbmRpZGF0ZV9vZmZpY2Vfc3RhdGUsIC1jYW5kaWRhdGVfb2ZmaWNlX3N0YXRlX2Z1bGwsIC1jYW5kaWRhdGVfb2ZmaWNlX2Rpc3RyaWN0LCAtY29uZHVpdF9jb21taXR0ZWVfaWQsIC1jb25kdWl0X2NvbW1pdHRlZV9uYW1lLCAtY29uZHVpdF9jb21taXR0ZWVfc3RyZWV0MSwgLWNvbmR1aXRfY29tbWl0dGVlX3N0cmVldDIsIC1jb25kdWl0X2NvbW1pdHRlZV9jaXR5LCAtY29uZHVpdF9jb21taXR0ZWVfc3RhdGUsIC1jb25kdWl0X2NvbW1pdHRlZV96aXAsIC1kb25vcl9jb21taXR0ZWVfbmFtZSwgLW5hdGlvbmFsX2NvbW1pdHRlZV9ub25mZWRlcmFsX2FjY291bnQsIC1lbGVjdGlvbl90eXBlX2Z1bGwsIC1pbmNyZWFzZWRfbGltaXQsIC1pc19pbmRpdmlkdWFsKSB8PgoKcmVuYW1lKGNvbW1pdHRlZV9uYW1lID0gYGNvbW1pdHRlZV9uYW1lLi4uMmApIHw+CgpmaWx0ZXIocmVwb3J0X3llYXIgPT0gMjAyNCkKCgpjb2xuYW1lcyhjbGVhbmVkX2RhdGEpCmBgYAoKYGBge3J9Cm1vc3RfY29udHJpYnV0aW9ucyA8LSBjbGVhbmVkX2RhdGEgfD4Kc2VsZWN0KGNvbW1pdHRlZV9uYW1lLCBjb250cmlidXRpb25fcmVjZWlwdF9hbW91bnQpIHw+Cmdyb3VwX2J5KGNvbW1pdHRlZV9uYW1lKSB8PgpzdW1tYXJpemUodG90YWxfY29udHJpYnV0aW9uID0gc3VtKGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCwgbmEucm0gPSBUUlVFKSkgfD4KYXJyYW5nZShkZXNjKHRvdGFsX2NvbnRyaWJ1dGlvbikpIApjbGVhbmVkX2RhdGEgfD4KICAKd3JpdGVfY3N2KCJkYXRhL2NsZWFuZWRfbWRfc2VuYXRlX2NvbnRyaWJ1dGlvbnMuY3N2IikKZGF0YSA8LSByZWFkX2RlbGltKCJkYXRhL2NjbC50eHQiLCBkZWxpbSA9ICJ8IiwgY29sX25hbWVzID0gRkFMU0UpCgpjbGVhbmVkX2RhdGFfY2NsIDwtIGRhdGEgfD4KcmVuYW1lKGNhbmRpZGF0ZV9pZCA9IFgxLGNhbmRpZGF0ZV9lbGVjdGlvbl95ZWFyID0gWDIsIGZlY19lbGVjdGlvbl95ZWFyID0gWDMsIGNvbW1pdHRlZV9pZCA9IFg0LGNvbW1pdHRlZV90eXBlID0gWDUsY29tbWl0dGVlX2Rlc2lnbiA9IFg2LCBsaW5rYWdlX2lkID0gWDcpCmBgYAoKaW5uZXIgam9pbiB0aGUgY29tbWl0dGVlIGlkIGFuZCBmZWMgZWxlY3Rpb24geWVhcjogCgpgYGB7cn0Kam9pbmVkX2RhdGEgPC0gaW5uZXJfam9pbihjbGVhbmVkX2RhdGEsIGNsZWFuZWRfZGF0YV9jY2wsIGJ5ID0gYygiY29tbWl0dGVlX2lkIiwgImZlY19lbGVjdGlvbl95ZWFyIikpCmBgYAoKaW5zZXJ0IHRoZSBjYW5kaWRhdGUgZGF0YToKYGBge3J9CmNhbmRpZGF0ZV9kYXRhIDwtIHJlYWRfZGVsaW0oImRhdGEvY2FuZGlkYXRlX2RhdGEudHh0IiwgZGVsaW0gPSAifCIsIGNvbF9uYW1lcyA9IEZBTFNFKSB8PgogIHNlbGVjdChYMSwgWDIsIFgzLCBYNSkgfD4gCiByZW5hbWUoY2FuZGlkYXRlX2lkID0gWDEsIGNhbmRpZGF0ZV9uYW1lID0gWDIsIGNhbmRpZGF0ZV9wYXJ0eSA9IFg1KQoKY2FuZGlkYXRlX2pvaW5lZF9kYXRhIDwtIGlubmVyX2pvaW4oam9pbmVkX2RhdGEsIGNhbmRpZGF0ZV9kYXRhLCBieSA9YygiY2FuZGlkYXRlX2lkIikpCmBgYAppbmNsdWRlIG9ubHkgdGhlc2Ugcm93czogCgpgYGB7cn0KCmZpbmFsX2RhdGEgPC0gY2FuZGlkYXRlX2pvaW5lZF9kYXRhIHw+CnNlbGVjdChjb21taXR0ZWVfaWQsIGNvbW1pdHRlZV9uYW1lLCByZXBvcnRfeWVhciwgZW50aXR5X3R5cGVfZGVzYyxjb250cmlidXRvcl9wcmVmaXgsIGNvbnRyaWJ1dG9yX25hbWUsIGNvbnRyaWJ1dG9yX2ZpcnN0X25hbWUsIGNvbnRyaWJ1dG9yX2xhc3RfbmFtZSwgY29udHJpYnV0b3JfbWlkZGxlX25hbWUsIGNvbnRyaWJ1dG9yX3N0cmVldF8xLGNvbnRyaWJ1dG9yX2NpdHksIGNvbnRyaWJ1dG9yX3N0YXRlLCBjb250cmlidXRvcl96aXAsY29udHJpYnV0b3JfZW1wbG95ZXIsIGNvbnRyaWJ1dG9yX29jY3VwYXRpb24sIGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2RhdGUsIGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCwgY29udHJpYnV0b3JfYWdncmVnYXRlX3l0ZCxtZW1vX3RleHQscGRmX3VybCwgY2FuZGlkYXRlX2lkLCBjYW5kaWRhdGVfZWxlY3Rpb25feWVhcikKYGBgCgojUXVlc3Rpb24gMTogRG8gbW9yZSBNYXJ5bGFuZGVycyBkb25hdGUgdG8gaW4tc3RhdGUgb3Igb3V0LW9mLXN0YXRlIGNhbmRpZGF0ZXM/IAoKYGBge3J9CmZpbmFsX2RhdGFfc3RhdGVzIDwtIGZpbmFsX2RhdGEgfD4KICBtdXRhdGUoc3RhdGUgPSBzdWJzdHIoY2FuZGlkYXRlX2lkLCAzLCA0KSkKYGBgCgpgYGB7cn0Kc3RhdGVfY29udHJpYnV0aW9ucyA8LSBmaW5hbF9kYXRhX3N0YXRlcyB8PgogIGdyb3VwX2J5KHN0YXRlKSB8PgogIHN1bW1hcmlzZSgKICAgIGNvbnRyaWJ1dGlvbl9jb3VudCA9IG4oKSwgICAgICAgICAgICAgICAgCiAgICB0b3RhbF9jb250cmlidXRpb24gPSBzdW0oY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50LCBuYS5ybSA9IFRSVUUpICAKICApCmBgYAoKYGBge3J9Cm1hcnlsYW5kX2NvbnRyaWIgPC0gc3RhdGVfY29udHJpYnV0aW9ucyB8PgogIGZpbHRlcihzdGF0ZSA9PSAiTUQiKSB8PgogIHN1bW1hcmlzZSh0b3RhbF9tYXJ5bGFuZF9jb250cmliID0gc3VtKHRvdGFsX2NvbnRyaWJ1dGlvbiwgbmEucm0gPSBUUlVFKSkKCgpvdGhlcl9zdGF0ZXNfY29udHJpYiA8LSBzdGF0ZV9jb250cmlidXRpb25zIHw+CiAgZmlsdGVyKHN0YXRlICE9ICJNRCIpIHw+CiAgc3VtbWFyaXNlKHRvdGFsX290aGVyX3N0YXRlc19jb250cmliID0gc3VtKHRvdGFsX2NvbnRyaWJ1dGlvbiwgbmEucm0gPSBUUlVFKSkKCgpjb21wYXJpc29uIDwtIGRhdGEuZnJhbWUoCiAgc3RhdGUgPSBjKCJNYXJ5bGFuZCIsICJPdGhlciBTdGF0ZXMiKSwKICB0b3RhbF9jb250cmlidXRpb24gPSBjKG1hcnlsYW5kX2NvbnRyaWIkdG90YWxfbWFyeWxhbmRfY29udHJpYiwgb3RoZXJfc3RhdGVzX2NvbnRyaWIkdG90YWxfb3RoZXJfc3RhdGVzX2NvbnRyaWIpCikKYGBgCgoKI0Fuc3dlciAxOgpNb250YW5hIHdhcyBzdXJwcmlzaW5nbHkgdGhlIHN0YXRlIHdpdGggdGhlIG1vc3QgY29udHJpYnV0aW9ucyAtLS0gZWRnaW5nIE1hcnlsYW5kIHdpdGggMjAyIG1vcmUgY29udHJpYnV0aW9ucyBNYXJ5bGFuZC4gTWFyeWxhbmQgcmVjZWl2ZWQgdGhlIGhpZ2hlc3QgdG90YWwgc3VtIGhvd2V2ZXIsIHdpdGggJDUsNTE2LDU2Mi4yNC4gVGhhdCB3YXMgJDQsMDc0LDIyNi4wNyBtb3JlIHRoYW4gdGhlIG5leHQgaGlnaGVzdCBzdGF0ZSwgd2hpY2ggd2FzIE1vbnRhbmEuIFRoZSBvdGhlciBzdGF0ZXMgY29tYmluZWQgcmVjaWV2ZWQgJDcsMzU4LDk3MCwgYSBsaXR0bGUgbGVzcyB0aGFuIHR3byBtaWxsaW9uIG1vcmUgdGhhbiBqdXN0IHRoZSBzdGF0ZSBvZiBNYXJ5bGFuZC4gCgoKI1F1ZXN0aW9uIDI6IFdoaWNoIG91dC1vZi1zdGF0ZSBjYW5kaWRhdGVzIHJlY2VpdmVkIHRoZSBtb3N0IGRvbmF0aW9ucyBhbmQgdGhlIGdyZWF0ZXN0IGFtb3VudCBvZiBtb25leSBpbiBkb25hdGlvbnM/IAoKYGBge3J9CmZpbmFsX2RhdGFfbm9fbWQgPC0gZmluYWxfZGF0YV9zdGF0ZXMgfD4KICBmaWx0ZXIoc3RhdGUgIT0gIk1EIikKYGBgCgpgYGB7cn0KY29udHJpYnV0aW9uc19zdW1tYXJ5IDwtIGZpbmFsX2RhdGFfbm9fbWQgfD4KICBncm91cF9ieShjb21taXR0ZWVfbmFtZSkgfD4KICBzdW1tYXJpc2UoCiAgICBudW1fY29udHJpYnV0aW9ucyA9IG4oKSwgCiAgICB0b3RhbF9jb250cmlidXRpb25fc3VtID0gc3VtKGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCwgbmEucm0gPSBUUlVFKSAKICApIHw+CiAgYXJyYW5nZShjb21taXR0ZWVfbmFtZSkKYGBgCgojQW5zd2VyIDI6IApKb24gVGVzdGVyLCBTaGVycm9kIEJyb3duIGFuZCBSdWJlbiBHYWxsZWdvIHdlcmUgdGhlIHRvcCB0aHJlZSBpbiB0aGF0IG9yZGVyIGZvciBib3RoIGNvbnRyaWJ1dGlvbnMgcmVjaWV2ZWQgYW5kIHRoZSBzdW0gb2YgY29udHJpYnV0aW9ucy4gVGhlIHNpbWlsYXJpdHkgYmV0d2VlbiB0aGUgdGhyZWUgb2YgdGhlbSBpcyB0aGF0IHRoZXkgd2VyZSBhbGwgRGVtb2NyYXRzIHJ1bm5pbmcgaW4gdGlnaHRseSBjb250ZXN0ZWQgcmFjZXMuIEJyb3duIHdhcyB0aGUgb25seSB0byBsb3NlIGhpcyByYWNlLiBKb24gVGVzdGVyIGFsc28gY2xlYXJseSByZWNpZXZlZCBtb3JlIHRoYW4gdGhlIG90aGVyIHR3byAtLS0gd2hpY2ggZXhwbGFpbnMgd2h5IE1vbnRhbmEgcmVjZWl2ZWQgc28gbWFueSBtb3JlIG91dC1vZi1zdGF0ZSBjb250cmlidXRpb25zIHRoYW4gb3RoZXIgc3RhdGVzLiBNb250YW5hbnMgZm9yIFRlc3RlciByZWNlaXZlZCAzLDY3OSBtb3JlIGNvbnRyaWJ1dGlvbnMgYW5kICQyMzgsMDE3Ljk2IG1vcmUgaW4gdG90YWwgY29udHJpYnV0aW9ucyBjb21wYXJlZCB0byBGcmllbmRzIG9mIFNoZXJyb2QgQnJvd24uCgpXZSBjaG9zZSBub3QgdG8gZm9jdXMgb24gcmVmaW5pbmcgYW5kIGNvZGluZyB0aGlzIHF1ZXN0aW9uLiBMb29raW5nIGF0IGRvbmF0aW9ucyB0byBjYW5kaWRhdGVzIGxpa2UgVGVzdGVyIGFuZCBBbHNvYnJvb2tzIHdvdWxkIG5vdCBhbnN3ZXIgb3VyIG5ld3N3b3J0aGluZXNzIGJlY2F1c2Ugb3VyIGZvY3VzIGlzIG9uIHdoZXJlIHdlYWx0aHkgaW5kaXZpZHVhbHMnIG1vbmV5IGdvZXMgaW4gZWxlY3Rpb25zLiBXaGlsZSBpdCBpcyBpbnRlcmVzdGluZyB0aGF0IG91dC1vZi1zdGF0ZSBkb25hdGlvbnMgYWxpZ24gd2l0aCBjb21wZXRpdGl2ZSBTZW5hdGUgcmFjZXMsIHN1Y2ggYXMgTW9udGFuYSBhbmQgT2hpbywgdGhpcyBhbmFseXNpcyB3b3VsZCBwcmltYXJpbHkgaGlnaGxpZ2h0IGdlb2dyYXBoaWMgZG9uYXRpb24gdHJlbmRzIHJhdGhlciB0aGFuIHRoZSBiZWhhdmlvciBvZiBoaWdoLWluY29tZSBkb25vcnMuIE91ciBzdG9yeSBhaW1zIHRvIGRpc3BsYXkgaG93IHdlYWx0aHkgaW5kaXZpZHVhbHMsIHBhcnRpY3VsYXJseSBDRU9zLCB1c2UgdGhlaXIgZmluYW5jaWFsIHBvd2VyIGluIGVsZWN0aW9uIGRvbmF0aW9ucy4gRXhhbWluaW5nIHNwZWNpZmljIGNhbmRpZGF0ZXMgb3Igb3V0LW9mLXN0YXRlIGRvbmF0aW9ucyB3b3VsZCBub3QgcHJvdmlkZSB0aGUgc2FtZSBpbnNpZ2h0IGludG8gdGhlIHJvbGUgb2Ygd2VhbHRoIGFuZCBsZWFkZXJzaGlwIHBvc2l0aW9ucyBpbiBzaGFwaW5nIG92ZXJhbGwgZG9uYXRpb24gcGF0dGVybnMsIHdoaWNoIG1ha2VzIG91ciBmaW5kaW5ncyBuZXdzd29ydGh5LgoKSG93ZXZlciwgdGhlIG90aGVyIHF1ZXN0aW9ucyB3ZSBleHBsb3JlZCBwcm92aWRlZCB3ZXJlIG1vcmUgcmVsZXZhbnQuIEJ5IGZvY3VzaW5nIG9uIENFT3MsIHdlIHdlcmUgYWJsZSB0byBzaG93IHBhdHRlcm5zIG9mIGZpbmFuY2lhbCBpbmZsdWVuY2UgcmVzb25hdGluZyB3aXRoIHB1YmxpYyBpbnRlcmVzdC4gUGVvcGxlIGFyZSBvZnRlbiBtb3JlIGN1cmlvdXMgYWJvdXQgaG93IHdlYWx0aHkgaW5kaXZpZHVhbHMgc3BlbmQgdGhlaXIgbW9uZXksIGVzcGVjaWFsbHkgaW4gdGhlIGNvbnRleHQgb2YgZWxlY3Rpb25zLCBhbmQgd2UgZmVsdCB0aGF0IHRoZSBvdGhlciBxdWVzdGlvbnMgd2UgZXhwbG9yZWQgcHJvdmlkZWQgbW9yZSByZWxldmFudCBpbnNpZ2h0cyB0aGF0IGFsaWduZWQgd2l0aCBvdXIgcG90ZW50aWFsIG5ld3Mgc3RvcnkgYWJvdXQgd2hlcmUgd2VhbHRoeSBpbmRpdmlkdWFsc+KAmSBtb25leSBnb2VzIGluIGVsZWN0aW9ucy4KCiNRdWVzdGlvbiAzOiBXaGF0IGFyZSB0aGUgZGVtb2dyYXBoaWNzIG9mIHBlb3BsZSB3aG8gZG9uYXRlIHRvIE1hcnlsYW5kIHJhY2VzIG9ubHk/IFRvIG91dC1vZi1zdGF0ZSByYWNlcyBvbmx5PwoKU3RlcCAxOiBmaW5kIHBlb3BsZSB3aG8gZG9uYXRlIHRvIE9OTFkgTWFyeWxhbmQgcmFjZXMuCmBgYHtyfQoKbWFyeWxhbmRfb25seV9kb25vcnMgPC0gZmluYWxfZGF0YV9zdGF0ZXN8PgogIGdyb3VwX2J5KGNvbnRyaWJ1dG9yX25hbWUpIHw+ICAgICAgICAgICAgICAgIAogIHN1bW1hcml6ZShvbmx5X21kID0gYWxsKHN0YXRlID09ICJNRCIpKSB8PgogIGZpbHRlcihvbmx5X21kKSB8PiAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgc2VsZWN0KGNvbnRyaWJ1dG9yX25hbWUpICAgICAgICAgICAgICAgICAgICAKCmZ1bGxfbWFyeWxhbmRfb25seV9kb25vcnMgPC0gZmluYWxfZGF0YV9zdGF0ZXMgfD4KICAgZmlsdGVyKGNvbnRyaWJ1dG9yX25hbWUgJWluJSBtYXJ5bGFuZF9vbmx5X2Rvbm9ycyRjb250cmlidXRvcl9uYW1lKQoKCnppcHNfZnVsbF9tYXJ5bGFuZF9vbmx5X2Rvbm9ycyA8LSBmdWxsX21hcnlsYW5kX29ubHlfZG9ub3JzIHw+CiAgZ3JvdXBfYnkoY29udHJpYnV0b3JfbmFtZSwgY29udHJpYnV0b3JfemlwKSB8PgogIHN1bW1hcml6ZSgKICAgIG51bV9kb25hdGlvbnMgPSBuKCksICAgICAgICAgICAgIAogICAgdG90YWxfZG9uYXRlZCA9IHN1bShjb250cmlidXRpb25fcmVjZWlwdF9hbW91bnQpIAogICl8PgogIGFycmFuZ2UoZGVzYyhudW1fZG9uYXRpb25zKSkgIAoKbWRfemlwX3N1bW1hcnkgPC0gemlwc19mdWxsX21hcnlsYW5kX29ubHlfZG9ub3JzIHw+CiAgZ3JvdXBfYnkoY29udHJpYnV0b3JfemlwKSB8PiAgICAgICAgICAgICAgCiAgc3VtbWFyaXplKAogICAgbnVtX2RvbmF0aW9ucyA9IG4oKSwgICAgICAgICAgICAgICAgICAgICAgCiAgICB0b3RhbF9kb25hdGVkID0gc3VtKHRvdGFsX2RvbmF0ZWQpICAgICAgCiAgKSB8PgogIGFycmFuZ2UoZGVzYyhudW1fZG9uYXRpb25zKSkgCgpgYGAKYGBge3J9CmFsbF96Y3RhIDwtIGdldF9hY3MoCiAgZ2VvZ3JhcGh5ID0gInpjdGEiLAogIHZhcmlhYmxlcyA9IGMoCiAiQjAxMDAzXzAwMSIsIAogICAgICJCMDEwMDJfMDAxIiwgIz0gIm1lZGlhbl9hZ2UiLAogIkIxOTAxM18wMDEiLCAjID0gIm1lZGlhbl9pbmNvbWUiLAogICJCMDIwMDFfMDAyIiwgIyA9ICJ3aGl0ZV9hbG9uZSIsCiAgICAgIkIwMjAwMV8wMDMiLCAjID0gImJsYWNrX2Fsb25lIiwKIkIwMjAwMV8wMDQiLCAjID0gIm5hdGl2ZV9hbWVyaWNhbiIsCiAgICAiQjAyMDAxXzAwNSIsICM9ICJhc2lhbl9hbG9uZSIsCiAiQjAyMDAxXzAwNiIsICMgPSAiaGF3YWlpYW5fcGFjaWZpYyIsCiJCMDIwMDFfMDA3IiwgICMgPSAib3RoZXJfcmFjZSIsCiAgICAiQjAyMDAxXzAwOCIsICMgPSAidHdvX29yX21vcmVfcmFjZXMiCiJCMDMwMDJfMDEyRSIpLAogIAogIHllYXIgPSAyMDIyLAogIHN1cnZleSA9ICJhY3M1IiwKICBvdXRwdXQgPSAid2lkZSIKKQoKYWxsX3pjdGEgPC0gYWxsX3pjdGEgJT4lCiAgcmVuYW1lKAogICAgdG90YWxfcG9wdWxhdGlvbiA9IEIwMTAwM18wMDFFLCAgICAgIAogICAgbWVkaWFuX2FnZSA9IEIwMTAwMl8wMDFFLCAgICAgICAgICAgIAogICAgbWVkaWFuX2luY29tZSA9IEIxOTAxM18wMDFFLCAgICAgICAgCiAgICB3aGl0ZV9hbG9uZSA9IEIwMjAwMV8wMDJFLCAgICAgICAgICAKICAgIGJsYWNrX2Fsb25lID0gQjAyMDAxXzAwM0UsICAgICAgICAgCiAgICBuYXRpdmVfYW1lcmljYW4gPSBCMDIwMDFfMDA0RSwgICAgICAKICAgIGFzaWFuX2Fsb25lID0gQjAyMDAxXzAwNUUsICAgICAgICAgIAogICAgaGF3YWlpYW5fcGFjaWZpYyA9IEIwMjAwMV8wMDZFLCAgICAgCiAgICBvdGhlcl9yYWNlID0gQjAyMDAxXzAwN0UsICAgICAgICAgICAKICAgIHR3b19vcl9tb3JlX3JhY2VzID0gQjAyMDAxXzAwOEUsCiAgICBoaXNwYW5pY19vcl9sYXRpbm8gPSBCMDMwMDJfMDEyRQogICkKCmBgYApgYGB7cn0KCnppcHNfZnVsbF9tYXJ5bGFuZF9vbmx5X2Rvbm9ycyA8LSB6aXBzX2Z1bGxfbWFyeWxhbmRfb25seV9kb25vcnMgfD4KICBtdXRhdGUoCiAgICBjb250cmlidXRvcl96aXAgPSBzdWJzdHIoY29udHJpYnV0b3JfemlwLCAxLCA1KSwKICAgIGNvbnRyaWJ1dG9yX3ppcCA9IHNwcmludGYoIiUwNXMiLCBjb250cmlidXRvcl96aXApCiAgKQoKemlwc19mdWxsX21hcnlsYW5kX29ubHlfZG9ub3JzIDwtIHppcHNfZnVsbF9tYXJ5bGFuZF9vbmx5X2Rvbm9ycyB8PgogIG11dGF0ZShjb250cmlidXRvcl96aXAgPSBhcy5jaGFyYWN0ZXIoY29udHJpYnV0b3JfemlwKSkKCm1lcmdlZF9kYXRhX21kIDwtIHppcHNfZnVsbF9tYXJ5bGFuZF9vbmx5X2Rvbm9ycyAlPiUKICBsZWZ0X2pvaW4oYWxsX3pjdGEsIGJ5ID0gYygiY29udHJpYnV0b3JfemlwIiA9ICJHRU9JRCIpKQoKc3VtbWFyaXplZF9tZF9kb25vcl9kZW1vc19ieV96aXAgPC0gbWVyZ2VkX2RhdGFfbWQgJT4lCiAgZ3JvdXBfYnkoY29udHJpYnV0b3JfemlwKSB8PgogIHN1bW1hcml6ZSgKICAgIHRvdGFsX3BvcHVsYXRpb24gPSBmaXJzdCh0b3RhbF9wb3B1bGF0aW9uKSwgIAogICAgbWVkaWFuX2FnZSA9IGZpcnN0KG1lZGlhbl9hZ2UpLCAgICAgICAgICAgICAKICAgIG1lZGlhbl9pbmNvbWUgPSBmaXJzdChtZWRpYW5faW5jb21lKSwgICAgICAgCiAgICB3aGl0ZV9hbG9uZSA9IGZpcnN0KHdoaXRlX2Fsb25lKSwgICAgICAgICAgICAKICAgIGJsYWNrX2Fsb25lID0gZmlyc3QoYmxhY2tfYWxvbmUpLCAgICAgICAgICAgCiAgICBuYXRpdmVfYW1lcmljYW4gPSBmaXJzdChuYXRpdmVfYW1lcmljYW4pLCAgIAogICAgYXNpYW5fYWxvbmUgPSBmaXJzdChhc2lhbl9hbG9uZSksICAgICAgICAgICAKICAgIGhhd2FpaWFuX3BhY2lmaWMgPSBmaXJzdChoYXdhaWlhbl9wYWNpZmljKSwgIAogICAgb3RoZXJfcmFjZSA9IGZpcnN0KG90aGVyX3JhY2UpLCAgCiAgICAgaGlzcGFuaWNfb3JfbGF0aW5vID0gZmlyc3QoaGlzcGFuaWNfb3JfbGF0aW5vKSwKICAgIHR3b19vcl9tb3JlX3JhY2VzID0gZmlyc3QodHdvX29yX21vcmVfcmFjZXMpLAogICAgbnVtX2RvbmF0aW9ucyA9IG4oKSwgICAgICAgICAgICAgICAgICAgICAgCiAgICB0b3RhbF9hbXRfZG9uYXRlZCA9IHN1bSh0b3RhbF9kb25hdGVkLCBuYS5ybSA9IFRSVUUpIAogICkgfD4gCiAgYXJyYW5nZShkZXNjKG51bV9kb25hdGlvbnMpKSAgfD4gCiAgbXV0YXRlKAogICAgd2hpdGVfYWxvbmVfcGVyX2NhcGl0YSA9IHdoaXRlX2Fsb25lIC8gdG90YWxfcG9wdWxhdGlvbiwKICAgIGJsYWNrX2Fsb25lX3Blcl9jYXBpdGEgPSBibGFja19hbG9uZSAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICBuYXRpdmVfYW1lcmljYW5fcGVyX2NhcGl0YSA9IG5hdGl2ZV9hbWVyaWNhbiAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICBhc2lhbl9hbG9uZV9wZXJfY2FwaXRhID0gYXNpYW5fYWxvbmUgLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgaGF3YWlpYW5fcGFjaWZpY19wZXJfY2FwaXRhID0gaGF3YWlpYW5fcGFjaWZpYyAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICBvdGhlcl9yYWNlX3Blcl9jYXBpdGEgPSBvdGhlcl9yYWNlIC8gdG90YWxfcG9wdWxhdGlvbiwKICAgICBoaXNwYW5pY19vcl9sYXRpbm9fcGVyX2NhcGl0YSA9IGhpc3BhbmljX29yX2xhdGlubyAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICB0d29fb3JfbW9yZV9yYWNlc19wZXJfY2FwaXRhID0gdHdvX29yX21vcmVfcmFjZXMgLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgbWVkaWFuX2luY29tZV9wZXJfY2FwaXRhID0gbWVkaWFuX2luY29tZSAvIHRvdGFsX3BvcHVsYXRpb24KICApIHw+CiAgIG11dGF0ZSgKICAgIHdoaXRlX2Fsb25lX3BlcmNlbnQgPSB3aGl0ZV9hbG9uZV9wZXJfY2FwaXRhICogMTAwLAogICAgYmxhY2tfYWxvbmVfcGVyY2VudCA9IGJsYWNrX2Fsb25lX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBuYXRpdmVfYW1lcmljYW5fcGVyY2VudCA9IG5hdGl2ZV9hbWVyaWNhbl9wZXJfY2FwaXRhICogMTAwLAogICAgYXNpYW5fYWxvbmVfcGVyY2VudCA9IGFzaWFuX2Fsb25lX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBoYXdhaWlhbl9wYWNpZmljX3BlcmNlbnQgPSBoYXdhaWlhbl9wYWNpZmljX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBvdGhlcl9yYWNlX3BlcmNlbnQgPSBvdGhlcl9yYWNlX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBoaXNwYW5pY19vcl9sYXRpbm9fcGVyY2VudCA9IGhpc3BhbmljX29yX2xhdGlub19wZXJfY2FwaXRhICoxMDAsCiAgICB0d29fb3JfbW9yZV9yYWNlc19wZXJjZW50ID0gdHdvX29yX21vcmVfcmFjZXNfcGVyX2NhcGl0YSAqIDEwMCwKICAgIG1lZGlhbl9pbmNvbWVfcGVyX2NhcGl0YSA9IG1lZGlhbl9pbmNvbWVfcGVyX2NhcGl0YSAqIDEwMAogICkgfD4KIG11dGF0ZSgKICAgIGFtdF9kb25hdGVkX3Blcl9yZXNpZGVudCA9IHRvdGFsX2FtdF9kb25hdGVkIC8gdG90YWxfcG9wdWxhdGlvbgogICkgfD4gICAKICBzZWxlY3Qod2hlcmUofiAhYWxsKGlzLm5hKC4pKSkpCgoKYGBgCmBgYHtyfQoKY2xlYW5lcl9tZF9kb25vcl9kZW1vcyA8LSBzdW1tYXJpemVkX21kX2Rvbm9yX2RlbW9zX2J5X3ppcCB8PiAKICAgIHNlbGVjdCgtbWF0Y2hlcygiX3Blcl9jYXBpdGEiKSwgLSJuYXRpdmVfYW1lcmljYW4iLCAtImhhd2FpaWFuX3BhY2lmaWMiLCAtIm90aGVyX3JhY2UiLCAtInR3b19vcl9tb3JlX3JhY2VzIiwgLSJ3aGl0ZV9hbG9uZSIsIC0iYmxhY2tfYWxvbmUiLCAtImFzaWFuX2Fsb25lIikgCiAKCgpgYGAKcmVwZWF0IGZvciBvdXQgb2Ygc3RhdGUgZG9ub3JzOiAKCmBgYHtyfQpvdXRfb2Zfc3RhdGVfZG9ub3JzIDwtIGZpbmFsX2RhdGFfc3RhdGVzIHw+CiAgZmlsdGVyKHN0YXRlICE9ICJNRCIpCgp4bWFyeWxhbmRfZG9ub3JzIDwtIGZpbmFsX2RhdGFfc3RhdGVzIHw+CiAgZmlsdGVyKHN0YXRlID09ICJNRCIpCgpvdXRfb2Zfc3RhdGVfb25seV9kb25vcnMgPC0gb3V0X29mX3N0YXRlX2Rvbm9ycyB8PgogIGZpbHRlcighY29udHJpYnV0b3JfbmFtZSAlaW4lIHhtYXJ5bGFuZF9kb25vcnMkY29udHJpYnV0b3JfbmFtZSkgIHw+Cmdyb3VwX2J5KGNvbnRyaWJ1dG9yX25hbWUsIGNvbnRyaWJ1dG9yX3ppcCkgfD4KICBzdW1tYXJpemUoCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgICAgICAgICAgIAogICAgdG90YWxfZG9uYXRlZCA9IHN1bShjb250cmlidXRpb25fcmVjZWlwdF9hbW91bnQpICAKICApIHw+CiAgYXJyYW5nZShkZXNjKG51bV9kb25hdGlvbnMpKSAgCgoKb3V0X29mX3N0YXRlX29ubHlfZG9ub3JzIDwtIG91dF9vZl9zdGF0ZV9vbmx5X2Rvbm9ycyB8PgogIG11dGF0ZSgKICAgIGNvbnRyaWJ1dG9yX3ppcCA9IHN1YnN0cihjb250cmlidXRvcl96aXAsIDEsIDUpLAogICAgY29udHJpYnV0b3JfemlwID0gc3ByaW50ZigiJTA1cyIsIGNvbnRyaWJ1dG9yX3ppcCkKICApCgoKYGBgCmBgYHtyfQoKbWVyZ2VkX2RhdGFfb29zIDwtIG91dF9vZl9zdGF0ZV9vbmx5X2Rvbm9yc3w+CiAgbGVmdF9qb2luKGFsbF96Y3RhLCBieSA9IGMoImNvbnRyaWJ1dG9yX3ppcCIgPSAiR0VPSUQiKSkKCmNsZWFuZXJfb29zX2Rvbm9yX2RlbW9zIDwtIG1lcmdlZF9kYXRhX29vcyAgfD4KICAgZ3JvdXBfYnkoY29udHJpYnV0b3JfemlwKSB8PgogIHN1bW1hcml6ZSgKICAgIHRvdGFsX3BvcHVsYXRpb24gPSBmaXJzdCh0b3RhbF9wb3B1bGF0aW9uKSwgCiAgICBtZWRpYW5fYWdlID0gZmlyc3QobWVkaWFuX2FnZSksICAgICAgICAgICAgICAKICAgIG1lZGlhbl9pbmNvbWUgPSBmaXJzdChtZWRpYW5faW5jb21lKSwgICAgICAgIAogICAgd2hpdGVfYWxvbmUgPSBmaXJzdCh3aGl0ZV9hbG9uZSksICAgICAgICAgCiAgICBibGFja19hbG9uZSA9IGZpcnN0KGJsYWNrX2Fsb25lKSwgICAgICAgICAgICAKICAgIG5hdGl2ZV9hbWVyaWNhbiA9IGZpcnN0KG5hdGl2ZV9hbWVyaWNhbiksICAgCiAgICBhc2lhbl9hbG9uZSA9IGZpcnN0KGFzaWFuX2Fsb25lKSwgICAgICAgICAgIAogICAgaGF3YWlpYW5fcGFjaWZpYyA9IGZpcnN0KGhhd2FpaWFuX3BhY2lmaWMpLAogICAgb3RoZXJfcmFjZSA9IGZpcnN0KG90aGVyX3JhY2UpLCAgICAgCiAgICBoaXNwYW5pY19vcl9sYXRpbm8gPSBmaXJzdChoaXNwYW5pY19vcl9sYXRpbm8pLAogICAgdHdvX29yX21vcmVfcmFjZXMgPSBmaXJzdCh0d29fb3JfbW9yZV9yYWNlcyksCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgICAgICAgICAgICAgICAgICAgICAKICAgIHRvdGFsX2FtdF9kb25hdGVkID0gc3VtKHRvdGFsX2RvbmF0ZWQsIG5hLnJtID0gVFJVRSkgCiAgKSB8PiAKICBhcnJhbmdlKGRlc2MobnVtX2RvbmF0aW9ucykpICB8PiAKICBtdXRhdGUoCiAgIAogICAgd2hpdGVfYWxvbmVfcGVyX2NhcGl0YSA9IHdoaXRlX2Fsb25lIC8gdG90YWxfcG9wdWxhdGlvbiwKICAgIGJsYWNrX2Fsb25lX3Blcl9jYXBpdGEgPSBibGFja19hbG9uZSAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICBuYXRpdmVfYW1lcmljYW5fcGVyX2NhcGl0YSA9IG5hdGl2ZV9hbWVyaWNhbiAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICBhc2lhbl9hbG9uZV9wZXJfY2FwaXRhID0gYXNpYW5fYWxvbmUgLyB0b3RhbF9wb3B1bGF0aW9uLAogICAgaGF3YWlpYW5fcGFjaWZpY19wZXJfY2FwaXRhID0gaGF3YWlpYW5fcGFjaWZpYyAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICBvdGhlcl9yYWNlX3Blcl9jYXBpdGEgPSBvdGhlcl9yYWNlIC8gdG90YWxfcG9wdWxhdGlvbiwKICAgIGhpc3BhbmljX29yX2xhdGlub19wZXJfY2FwaXRhID0gaGlzcGFuaWNfb3JfbGF0aW5vIC8gdG90YWxfcG9wdWxhdGlvbiwKICAgIHR3b19vcl9tb3JlX3JhY2VzX3Blcl9jYXBpdGEgPSB0d29fb3JfbW9yZV9yYWNlcyAvIHRvdGFsX3BvcHVsYXRpb24sCiAgICBtZWRpYW5faW5jb21lX3Blcl9jYXBpdGEgPSBtZWRpYW5faW5jb21lIC8gdG90YWxfcG9wdWxhdGlvbgogICkgfD4KICAgbXV0YXRlKAogIAogICAgd2hpdGVfYWxvbmVfcGVyY2VudCA9IHdoaXRlX2Fsb25lX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBibGFja19hbG9uZV9wZXJjZW50ID0gYmxhY2tfYWxvbmVfcGVyX2NhcGl0YSAqIDEwMCwKICAgIG5hdGl2ZV9hbWVyaWNhbl9wZXJjZW50ID0gbmF0aXZlX2FtZXJpY2FuX3Blcl9jYXBpdGEgKiAxMDAsCiAgICBhc2lhbl9hbG9uZV9wZXJjZW50ID0gYXNpYW5fYWxvbmVfcGVyX2NhcGl0YSAqIDEwMCwKICAgIGhhd2FpaWFuX3BhY2lmaWNfcGVyY2VudCA9IGhhd2FpaWFuX3BhY2lmaWNfcGVyX2NhcGl0YSAqIDEwMCwKICAgIG90aGVyX3JhY2VfcGVyY2VudCA9IG90aGVyX3JhY2VfcGVyX2NhcGl0YSAqIDEwMCwKICAgIGhpc3BhbmljX29yX2xhdGlub19wZXJjZW50ID0gaGlzcGFuaWNfb3JfbGF0aW5vX3Blcl9jYXBpdGEgKjEwMCwKICAgIHR3b19vcl9tb3JlX3JhY2VzX3BlcmNlbnQgPSB0d29fb3JfbW9yZV9yYWNlc19wZXJfY2FwaXRhICogMTAwLAogICAgbWVkaWFuX2luY29tZV9wZXJfY2FwaXRhID0gbWVkaWFuX2luY29tZV9wZXJfY2FwaXRhICogMTAwICAKICApIAoKY2xlYW5lcl9vb3NfZG9ub3JfZGVtb3MgPC0gY2xlYW5lcl9vb3NfZG9ub3JfZGVtb3MgfD4gc2VsZWN0KC1tYXRjaGVzKCJfcGVyX2NhcGl0YSIpLCAtIm5hdGl2ZV9hbWVyaWNhbiIsIC0iaGF3YWlpYW5fcGFjaWZpYyIsIC0ib3RoZXJfcmFjZSIsIC0idHdvX29yX21vcmVfcmFjZXMiLCAtIndoaXRlX2Fsb25lIiwgLSJibGFja19hbG9uZSIsIC0iYXNpYW5fYWxvbmUiKSB8PiAKICAKICBtdXRhdGUoCiAgICBhbXRfZG9uYXRlZF9wZXJfcmVzaWRlbnQgPSB0b3RhbF9hbXRfZG9uYXRlZCAvIHRvdGFsX3BvcHVsYXRpb24KICApIHw+CiAgc2VsZWN0KHdoZXJlKH4gIWFsbChpcy5uYSguKSkpKQoKCmBgYApgYGB7cn0KaGVhZChtZXJnZWRfZGF0YV9vb3MpCmBgYAoKCmBgYHtyfQpjbGVhbmVyX29vc19kb25vcl9kZW1vcyA8LSBjbGVhbmVyX29vc19kb25vcl9kZW1vcyB8PiAgIAogIG11dGF0ZSgKICAgIGNvbnRyaWJ1dG9yX3ppcCA9IGFzLmNoYXJhY3Rlcihjb250cmlidXRvcl96aXApLCAgICAgICAgICMgRW5zdXJlIFpJUCBjb2RlcyBhcmUgc3RyaW5ncwogICAgY29udHJpYnV0b3JfemlwID0gc3RyX3BhZChjb250cmlidXRvcl96aXAsIHdpZHRoID0gNSwgICAgIyBQYWQgd2l0aCBsZWFkaW5nIHplcm9zIHRvIGVuc3VyZSA1IGRpZ2l0cwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaWRlID0gImxlZnQiLCBwYWQgPSAiMCIpLAogICAgY29udHJpYnV0b3JfemlwID0gaWZlbHNlKHN0cl9kZXRlY3QoY29udHJpYnV0b3JfemlwLCAiXlxcZHs1fSQiKSwgICMgS2VlcCBvbmx5IHZhbGlkIDUtZGlnaXQgWklQIGNvZGVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJpYnV0b3JfemlwLCBOQSkpICB8PgptdXRhdGUoY29udHJpYnV0b3JfemlwID0gaWZlbHNlKGNvbnRyaWJ1dG9yX3ppcCA9PSAiMzA2MzkiLCAiMjA2MzkiLCBjb250cmlidXRvcl96aXApKQoKCgpjbGVhbmVyX29vc19kb25vcl9kZW1vcyB8PiBhcnJhbmdlKGRlc2MoYW10X2RvbmF0ZWRfcGVyX3Jlc2lkZW50KSkgfD4gd3JpdGVfY3N2KCJjbGVhbmVyX29vc19kb25vcl9kZW1vcy5jc3YiKQoKYGBgCgpgYGB7cn0KY2xlYW5lcl9tZF9kb25vcl9kZW1vcyA8LSBjbGVhbmVyX21kX2Rvbm9yX2RlbW9zIHw+IAogIG11dGF0ZSgKICAgIGNvbnRyaWJ1dG9yX3ppcCA9IGFzLmNoYXJhY3Rlcihjb250cmlidXRvcl96aXApLCAgICAgICAgICMgRW5zdXJlIFpJUCBjb2RlcyBhcmUgc3RyaW5ncwogICAgY29udHJpYnV0b3JfemlwID0gc3RyX3BhZChjb250cmlidXRvcl96aXAsIHdpZHRoID0gNSwgICAgIyBQYWQgd2l0aCBsZWFkaW5nIHplcm9zIHRvIGVuc3VyZSA1IGRpZ2l0cwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaWRlID0gImxlZnQiLCBwYWQgPSAiMCIpLAogICAgY29udHJpYnV0b3JfemlwID0gaWZlbHNlKHN0cl9kZXRlY3QoY29udHJpYnV0b3JfemlwLCAiXlxcZHs1fSQiKSwgICMgS2VlcCBvbmx5IHZhbGlkIDUtZGlnaXQgWklQIGNvZGVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJpYnV0b3JfemlwLCBOQSkpIAoKY2xlYW5lcl9tZF9kb25vcl9kZW1vc3w+ICBhcnJhbmdlKGRlc2MoYW10X2RvbmF0ZWRfcGVyX3Jlc2lkZW50KSkgfD4gd3JpdGVfY3N2KCJjbGVhbmVyX21kX2Rvbm9yX2RlbW9zLmNzdiIpCmBgYAoKCmBgYHtyfQp0b3BfY2xlYW5lcl9tZF9kb25vcl9kZW1vcyA8LSBjbGVhbmVyX21kX2Rvbm9yX2RlbW9zIHw+CiBhcnJhbmdlKGRlc2MoYW10X2RvbmF0ZWRfcGVyX3Jlc2lkZW50KSkgfD4KICBzbGljZV9oZWFkKG4gPSA1KQoKd3JpdGVfY3N2KHRvcF9jbGVhbmVyX21kX2Rvbm9yX2RlbW9zLCAidG9wX2NsZWFuZXJfbWRfZG9ub3JfZGVtb3MuY3N2IikKCmBgYAoKYGBge3J9CnRvcF9jbGVhbmVyX29vc19kb25vcl9kZW1vcyA8LSBjbGVhbmVyX29vc19kb25vcl9kZW1vcyB8PgogICAgYXJyYW5nZShkZXNjKGFtdF9kb25hdGVkX3Blcl9yZXNpZGVudCkpIHw+CiAgc2xpY2VfaGVhZChuID0gNSkKCndyaXRlX2Nzdih0b3BfY2xlYW5lcl9vb3NfZG9ub3JfZGVtb3MsICJ0b3BfY2xlYW5lcl9vb3NfZG9ub3JfZGVtb3MuY3N2IikKYGBgCgpgYGB7cn0KCmNsZWFuZXJfb29zX2Rvbm9yX2RlbW9zIDwtIGNsZWFuZXJfb29zX2Rvbm9yX2RlbW9zIHw+IAogIGFycmFuZ2UoZGVzYyhhbXRfZG9uYXRlZF9wZXJfcmVzaWRlbnQpKQoKY2xlYW5lcl9tZF9kb25vcl9kZW1vcyA8LSBjbGVhbmVyX21kX2Rvbm9yX2RlbW9zIHw+IAogIGFycmFuZ2UoZGVzYyhhbXRfZG9uYXRlZF9wZXJfcmVzaWRlbnQpKQpgYGAKCmBgYHtyfQoKI0NyZWF0aW5nIHRhYmxlIGNvbXBhcmluZyBkZW1vZ3JhcGhpY3Mgb2YgZG9ub3JzIHRvIGluLXN0YXRlIGFuZCBvdXQtb2Ytc3RhdGUgZWxlY3Rpb25zLgoKb29zX2F2ZXJhZ2VzIDwtIGNsZWFuZXJfb29zX2Rvbm9yX2RlbW9zIHw+IAogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gaWZlbHNlKGlzLmluZmluaXRlKC4pLCBOQSwgLikpKSB8PgogICBzdW1tYXJpemUoCiAgICAgICAgICAgIHdoaXRlX3BjdCA9IG1lYW4od2hpdGVfYWxvbmVfcGVyY2VudCwgbmEucm0gPSBUUlVFKSwgCiAgICAgICAgICAgIGJsYWNrX3BjdCA9IG1lYW4oYmxhY2tfYWxvbmVfcGVyY2VudCwgbmEucm0gPSBUUlVFKSwgCiAgICAgICAgICAgIG5hdGl2ZV9hbWVyaWNhbl9wY3QgPSBtZWFuKG5hdGl2ZV9hbWVyaWNhbl9wZXJjZW50LCBuYS5ybSA9IFRSVUUpLCAKICAgICAgICAgICAgYXNpYW5fcGN0ID0gbWVhbihhc2lhbl9hbG9uZV9wZXJjZW50LCBuYS5ybSA9IFRSVUUpLCAKICAgICAgICAgICAgaGF3YWlpYW5fcGFjaWZpY19wY3QgPSBtZWFuKGhhd2FpaWFuX3BhY2lmaWNfcGVyY2VudCwgbmEucm0gPSBUUlVFKSwgCiAgICAgICAgICAgIG90aGVyX3JhY2VfcGN0ID0gbWVhbihvdGhlcl9yYWNlX3BlcmNlbnQsIG5hLnJtID0gVFJVRSksIAogICAgICAgICAgICBoaXNwYW5pY19vcl9sYXRpbm9fcGN0ID0gbWVhbihoaXNwYW5pY19vcl9sYXRpbm9fcGVyY2VudCwgbmEucm0gPSBUUlVFKSwgCiAgICAgICAgICAgIHR3b19vcl9tb3JlX3JhY2VzX3BjdCA9IG1lYW4odHdvX29yX21vcmVfcmFjZXNfcGVyY2VudCwgbmEucm0gPSBUUlVFKSwgCiAgICAgICAgICAgIGFtdF9kb25hdGVkX3Blcl9yZXNpZGVudCA9IG1lYW4oYW10X2RvbmF0ZWRfcGVyX3Jlc2lkZW50LCBuYS5ybSA9IFRSVUUpLCAKICAgICAgICAgICAgbWVkaWFuX2FnZSA9IG1lZGlhbihtZWRpYW5fYWdlLG5hLnJtID0gVFJVRSksIAogICAgICAgICAgICBtZWRpYW5faW5jb21lID0gbWVkaWFuKG1lZGlhbl9pbmNvbWUsIG5hLnJtID0gVFJVRSksCiAgIHRvdGFsX251bV9kb25hdGlvbnMgPSBzdW0obnVtX2RvbmF0aW9ucywgbmEucm0gPSBUUlVFKSwKICAgIHRvdGFsX2FtdF9kb25hdGlvbnMgPSBzdW0odG90YWxfYW10X2RvbmF0ZWQsIG5hLnJtID0gVFJVRSksIApyYWNlX2RvbmF0ZWQgPSBjKCJvdXRfb2Zfc3RhdGUiKSkgfD4gIAogIHNlbGVjdChyYWNlX2RvbmF0ZWQsIGV2ZXJ5dGhpbmcoKSkgfD4gCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5udW1lcmljKSwgfiByb3VuZCguICwgMikpKSB8PiAKd3JpdGVfY3N2KCJvb3NfYXZlcmFnZXMuY3N2IikKCiAgCm1kX2F2ZXJhZ2VzIDwtIGNsZWFuZXJfbWRfZG9ub3JfZGVtb3MgfD4gCiAgc3VtbWFyaXplKAogICAgICAgICAgICB3aGl0ZV9wY3QgPSBtZWFuKHdoaXRlX2Fsb25lX3BlcmNlbnQsIG5hLnJtID0gVFJVRSksIAogICAgICAgICAgICBibGFja19wY3QgPSBtZWFuKGJsYWNrX2Fsb25lX3BlcmNlbnQsIG5hLnJtID0gVFJVRSksIAogICAgICAgICAgICBuYXRpdmVfYW1lcmljYW5fcGN0ID0gbWVhbihuYXRpdmVfYW1lcmljYW5fcGVyY2VudCwgbmEucm0gPSBUUlVFKSwgCiAgICAgICAgICAgIGFzaWFuX3BjdCA9IG1lYW4oYXNpYW5fYWxvbmVfcGVyY2VudCwgbmEucm0gPSBUUlVFKSwgCiAgICAgICAgICAgIGhhd2FpaWFuX3BhY2lmaWNfcGN0ID0gbWVhbihoYXdhaWlhbl9wYWNpZmljX3BlcmNlbnQsIG5hLnJtID0gVFJVRSksIAogICAgICAgICAgICBvdGhlcl9yYWNlX3BjdCA9IG1lYW4ob3RoZXJfcmFjZV9wZXJjZW50LCBuYS5ybSA9IFRSVUUpLCAKICAgICAgICAgICAgaGlzcGFuaWNfb3JfbGF0aW5vX3BjdCA9IG1lYW4oaGlzcGFuaWNfb3JfbGF0aW5vX3BlcmNlbnQsIG5hLnJtID0gVFJVRSksIAogICAgICAgICAgICB0d29fb3JfbW9yZV9yYWNlc19wY3QgPSBtZWFuKHR3b19vcl9tb3JlX3JhY2VzX3BlcmNlbnQsIG5hLnJtID0gVFJVRSksIAogICAgICAgICAgICBhbXRfZG9uYXRlZF9wZXJfcmVzaWRlbnQgPSBtZWFuKGFtdF9kb25hdGVkX3Blcl9yZXNpZGVudCwgbmEucm0gPSBUUlVFKSwgCiAgICAgICAgICAgIG1lZGlhbl9hZ2UgPSBtZWRpYW4obWVkaWFuX2FnZSxuYS5ybSA9IFRSVUUpLCAKICAgICAgICAgICAgbWVkaWFuX2luY29tZSA9IG1lZGlhbihtZWRpYW5faW5jb21lLCBuYS5ybSA9IFRSVUUpLAogICB0b3RhbF9udW1fZG9uYXRpb25zID0gc3VtKG51bV9kb25hdGlvbnMsIG5hLnJtID0gVFJVRSksCiAgICB0b3RhbF9hbXRfZG9uYXRpb25zID0gc3VtKHRvdGFsX2FtdF9kb25hdGVkLCBuYS5ybSA9IFRSVUUpLCAKICAgcmFjZV9kb25hdGVkID0gYygibWFyeWxhbmQiKSkgfD4gCiAgc2VsZWN0KHJhY2VfZG9uYXRlZCwgZXZlcnl0aGluZygpKSB8PiAKICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCB+IHJvdW5kKC4gLCAyKSkpIHw+IAp3cml0ZV9jc3YoIm1kX2F2ZXJhZ2VzLmNzdiIpCiAgCmNvbWJpbmVkX2F2ZXJhZ2VzIDwtIGJpbmRfcm93cyhvb3NfYXZlcmFnZXMsIG1kX2F2ZXJhZ2VzKXw+CiAgd3JpdGVfY3N2KCJjb21iaW5lZF9hdmVyYWdlcy5jc3YiKSAKCkRhdGF3cmFwcGVyIHRhYmxlOiBodHRwczovL2RhdGF3cmFwcGVyLmR3Y2RuLm5ldC9uYzV1VC8xLwoKCmBgYAoKI0Fuc3dlciAzOiAKCkluIGFza2luZyBhbmQgYW5zd2VyaW5nIHRoaXMgcXVlc3Rpb24sIHdlIGF0dGVtcHQgdG8gdXNlIGRvbmF0aW9ucyBhcyBhIG1lYXN1cmUgb2YgYSBkb25vcidzIHBlcmNlcHRpb24gb2YgdGhlaXIgZG9uYXRpb24ncyBhYmlsaXR5IHRvIGltcGFjdCB0aGUgb3V0Y29tZSBvZiBhIHJhY2UsIG1lYW5pbmcgdGhhdCBwZW9wbGUgd2hvIGRvbmF0ZWQgKm9ubHkqIHRvIE1hcnlsYW5kJ3Mgc2VuYXRlIHJhY2UsIHdlIGluZmVyLCBkZXRlcm1pbmVkIHRoYXQgdGhlaXIgZG9uYXRpb24gd291bGQgYmUgbW9zdCBpbXBhY3RmdWwgdG8gdGhhdCByYWNlLiBDb252ZXJzZWx5LCBwZW9wbGUgd2hvIGRvbmF0ZWQgKm9ubHkqIHRvIG91dC1vZi1zdGF0ZSByYWNlcyBkZXRlcm1pbmVkIHRoYXQgdGhlaXIgZG9uYXRpb25zIHdlcmUgbW9zdCBuZWVkZWQgdG8gaW5mbHVlbmNlIHRob3NlIHJhY2VzLiAKCkl0IGlzIGNlcnRhaW5seSBwb3NzaWJsZSB0aGF0IGRvbm9ycyBnaXZlIG1vbmV5IHRvIGNhbmRpZGF0ZXMgZm9yIG90aGVyIHJlYXNvbnMgKE1heWJlIHRoZXkncmUganVzdCBhIGJpZyBmYW4gb2YgYSBjZXJ0YWluIHBvbGl0aWNhbikuIEhvd2V2ZXIsIGdpdmVuIHRoYXQgdGhlIHRvcCBvdXQtb2Ytc3RhdGUgZG9uYXRpb25zIHdlcmUgbWFkZSB0byBjYW5kaWRhdGVzIGluIGNvbXBldGl0aXZlIHJhY2VzLCBhbmQgdGhhdCBNYXJ5bGFuZCdzIHNlbmF0ZSByYWNlIHdhcyBjb21wZXRpdGl2ZSB0aGlzIHllYXIsIHdlIHRoaW5rIHRoaXMgaXMgYSByZWFzb25hYmxlIHRoZW9yeSB0aGF0IHdlIGNhbiB1c2UgdG8gaW50ZXJwcmV0IHRoaXMgZGF0YS4gCgpUbyBpbGx1c3RyYXRlIG91ciBmaW5kaW5ncywgSSBmaXJzdCBjcmVhdGVkIHR3byBEYXRhd3JhcHBlciBtYXBzIHNob3dpbmcgZG9uYXRpb24gYW1vdW50IHBlciBjYXBpdGEgYW5kIGRlbW9ncmFwaGljIGRhdGEsIGluY2x1ZGluZyBtZWRpYW4gaW5jb21lIGFuZCBhZ2UsIGFuZCByYWNpYWwgbWFrZXVwLiAKCkluLXN0YXRlIGVsZWN0aW9uIGRvbm9yczogaHR0cHM6Ly9kYXRhd3JhcHBlci5kd2Nkbi5uZXQvOTF1WUkvMS8KT3V0LW9mLXN0YXRlIGVsZWN0aW9uIGRvbm9yczogaHR0cHM6Ly9kYXRhd3JhcHBlci5kd2Nkbi5uZXQvUGxsUUMvMS8KCkZyb20gY29tcGFyaW5nIHRob3NlIG1hcHMsIGl0J3MgY2xlYXIgdGhhdCBNYXJ5bGFuZGVycyBpbiBjZXJ0YWluIHBhcnRzIG9mIHRoZSBzdGF0ZSAodGhlIHdlYWx0aHkgREMgc3VidXJicywgQW5uYXBvbGlzLCBhbmQgcGFydHMgb2YgVGFsYm90IGNvdW50eSkgZG9uYXRlIG1vcmUgbW9uZXksIHdoZXRoZXIgdGhleSBhcmUgZG9uYXRpbmcgdG8gaW4tc3RhdGUgb3Igb3V0LW9mLXN0YXRlIGVsZWN0aW9ucy4gCgpXZSBjYW4gc2VlIHRoYXQgZm9yIE1hcnlsYW5kIHJhY2VzLCBkb25vcnMgaW4gdGhvc2UgaGlnaC1kb25hdGlvbiBhcmVhcyBkb25hdGVkIHNpbWlsYXIgYW1vdW50cyBwZXIgY2FwaXRhLiBIb3dldmVyLCBmb3Igb3V0LW9mLXN0YXRlIHJhY2VzLCB0aGUgbGFyZ2VzdCBkb25hdGlvbnMgcGVyIGNhcGl0YSB3ZXJlIGNvbmNlbnRyYXRlZCBhcm91bmQgdGhlIERDIHN1YnVyYnMuIAoKVGhpcyBpcyBsaWtlbHkgYmVjYXVzZSBNYXJ5bGFuZCdzIHdlYWx0aGllc3QgZG9ub3JzIGxpdmUgaW4gdGhhdCBwYXJ0IG9mIHRoZSBzdGF0ZSwgYW5kIG1hZGUgbGFyZ2UgZG9uYXRpb25zIHRvIGNhbmRpZGF0ZXMgSm9uIFRlc3RlciwgU2hlcnJvZCBCcm93biBhbmQgUnViZW4gR2FsbGVnbyBpbiBhbiBlZmZvcnQgdG8gc3dheSBjb21wZXRpdGl2ZSByYWNlcyBpbiBzd2luZyBzdGF0ZXMuIAoKRG9uYXRpb25zIHRvIE1hcnlsYW5kIHJhY2VzIHdlcmUgbW9yZSBldmVubHkgZGlzcGVyc2VkIGFjcm9zcyB0aGUgc3RhdGUuIFRoaXMgbWF5IGJlIGJlY2F1c2UgdGhlIE1hcnlsYW5kIHJhY2Ugd2FzIGNvbXBldGl0aXZlIHRoaXMgeWVhciwgYW5kIE1hcnlsYW5kZXJzIGZlbHQgdGhhdCB0aGVpciBjb250cmlidXRpb25zIHRvIHRoZSBpbi1zdGF0ZSBzZW5hdGUgcmFjZSBjb3VsZCBtYWtlIGEgZGlmZmVyZW5jZSBpbiBzaGFwaW5nIHRoZSBvdXRjb21lIG9mIHRoZSBlbGVjdGlvbiAoYXMgb3Bwb3NlZCB0byBtb3JlIHR5cGljYWwgZWxlY3Rpb24geWVhcnMsIHdoZXJlIE1hcnlsYW5kIGlzIGFuIHVuY29udGVzdGVkIGJsdWUgc3RhdGUpLgoKSSBhbHNvIGZvdW5kIHRoYXQsIGNvbXBhcmluZyB0aGUgZGVtb2dyYXBoaWNzIG9mIHRoZSB0d28gZ3JvdXBzIGFnYWluc3QgZWFjaCBvdGhlciwgdGhleSB3ZXJlIHJlbWFya2FibGUgc2ltaWxhciBpbiBldmVyeSBmYWN0b3IgdGhhdCBJIG1lYXN1cmVkLiBUaGlzIG1pZ2h0IGltcGx5IHRoYXQgZGVtb2dyYXBoaWNzIGxpa2UgcmFjZSwgaW5jb21lLCBvciBhZ2UgZGlkIG5vdCBpbmZsdWVuY2UgYSBkb25vcidzIGxpa2xpaG9vZCB0byBkb25hdGUgaW4tc3RhdGUgdnMgb3V0LW9mLXN0YXRlLiAKCkkgY3JlYXRlZCB0aGlzIHRhYmxlIHdpdGggbXkgZmluZGluZ3M6IGh0dHBzOi8vZGF0YXdyYXBwZXIuZHdjZG4ubmV0L25jNXVULzEvCgoKIyBRdWVzdGlvbiA0OiBBbW9uZyB0b3AgTWFyeWxhbmQgZG9ub3JzLCB3aGF0IHByb2Zlc3Npb25zIGRvbmF0ZSB0aGUgbW9zdCBtb25leSB0byBzZW5hdGUgY2FtcGFpZ25zPyAKCgpgYGB7cn0KaW5kaXZpZHVhbF9kb25vcnMgIDwtIGZpbmFsX2RhdGFfc3RhdGVzfD4KZ3JvdXBfYnkoY29udHJpYnV0b3JfbmFtZSwgY29udHJpYnV0b3JfemlwLCBjb250cmlidXRvcl9vY2N1cGF0aW9uLCBjb250cmlidXRvcl9lbXBsb3llcikgfD4gCiAgc3VtbWFyaXplKAogICAgbnVtX2RvbmF0aW9ucyA9IG4oKSwgICAgICAgICAgICAgICAKICAgIHRvdGFsX2RvbmF0ZWQgPSBzdW0oY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50KSAKICApIHw+CiAgYXJyYW5nZShkZXNjKG51bV9kb25hdGlvbnMpKSAgCgpqb2JzX3RvX2NsZWFuIDwtIGluZGl2aWR1YWxfZG9ub3JzIHw+IAogIGdyb3VwX2J5KGNvbnRyaWJ1dG9yX29jY3VwYXRpb24pIHw+CiAgc3VtbWFyaXplKAogICAgbnVtYmVyX2pvYnMgPSBuKCksCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgCiAgICAgdG90YWxfZG9uYXRpb25zID0gc3VtKHRvdGFsX2RvbmF0ZWQpCiAgKSB8PiBhcnJhbmdlKGRlc2MobnVtYmVyX2pvYnMpKSB8Pgp3cml0ZV9jc3YoImRhdGEvam9ic190b19jbGVhbi5jc3YiKQoKYGBgCgpgYGB7cn0KYm9zc190b19jbGVhbiAgPC0gaW5kaXZpZHVhbF9kb25vcnMgfD4gCiAgZ3JvdXBfYnkoY29udHJpYnV0b3JfZW1wbG95ZXIpIHw+CiAgc3VtbWFyaXplKAogICAgbnVtYmVyX2pvYnMgPSBuKCksCiAgICBudW1fZG9uYXRpb25zID0gbigpLCAgCiAgICAgdG90YWxfZG9uYXRpb25zID0gc3VtKHRvdGFsX2RvbmF0ZWQpCiAgKSB8PiBhcnJhbmdlKGRlc2MobnVtYmVyX2pvYnMpKSB8Pgp3cml0ZV9jc3YoImRhdGEvYm9zc190b19jbGVhbi5jc3YiKQpgYGAKCgpgYGB7cn0KY2xlYW5fZW1wbG95ZXIgPC0gcmVhZF9jc3YoImRhdGEvY2xlYW5lZF9ib3NzLmNzdiIpCmNsZWFuX29jY3VwYXRpb24gPC0gcmVhZF9jc3YoImRhdGEvY2xlYW5fam9icy5jc3YiKQoKY2xlYW5fb2NjdXBhdGlvbiB8PiAKICBncm91cF9ieShjbGVhbmVkX2pqb2JzKSB8PiAKICBzdW1tYXJpemUoCiAgICBudW1iZXJfam9icyA9IG4oKSwKICAgIG51bV9kb25hdGlvbnMgPSBuKCksICAKICAgIHRvdGFsX2RvbmF0ZWQgPSBzdW0odG90YWxfZG9uYXRpb25zKSkgfD4gCiAgYXJyYW5nZShjbGVhbmVkX2pqb2JzKQoKYGBgCmBgYHtyfQoKCmNsZWFuX29jY3VwYXRpb24gPC0gcmVhZF9jc3YoImRhdGEvY2xlYW5fam9icy5jc3YiKQoKCmNsZWFuX29jY3VwYXRpb24gPC0gY2xlYW5fb2NjdXBhdGlvbiB8PiAKICBtdXRhdGUoY2xlYW5lZF9qam9icyA9IGNhc2Vfd2hlbigKICAgIGNvbnRyaWJ1dG9yX29jY3VwYXRpb24gJWluJSBjKCJDLkUuTy4iLCAiQ0VPIiwgIkNFTyAmIEZPVU5ERVIiLCAiQ0VPICYgTUVESUEgQ09OVFJJQlVUT1IiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRU8gJiBQUkVTSURFTlQiLCAiQ0VPIFVOREVSV1JJVElORyIsICJDRU8vQVVUSE9SIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0hBSVJNQU4sIENFTyBBTkQgUFJFU0lERU5UIiwgIkNISUVGIEVYRUNVVElWRSBPRkZJQ0VSIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ08tQ0VPIiwgIkNPLUZPVU5ERVIgJiBDRU8iLCAiUFJFU0lERU5UICYgQ0VPIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRk9VTkRFUiBDRU8iLCAiUFJFU0lERU5UICYgQy5FLk8uIiwgIlBSRVNJREVOVCAvIENFTyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBSRVNJREVOVCBDRU8iKSB+ICJDRU8iLAogICAgY29udHJpYnV0b3Jfb2NjdXBhdGlvbiAlaW4lIGMoIkRFUFVUWSIsICJERVBVVFkgQURNSU5JU1RSQVRPUiAmIERJUkVDVE9SIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiREVQVVRZIEFTU0lTVEFOVCBTRUNSRVRBUlkiLCAiREVQVVRZIENISUVGIEFETUlOSVNUUkFUSVZFIE9GRklDRVIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJERVBVVFkgQ09TIiwgIkRFUFVUWSBESVJFQ1RPUiIsICJERVBVVFkgUkVTRUFSQ0ggRElSRUNUT1IiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJERVBVVFkgU0VDUkVUQVJZIiwgIkRFUFVUWSBTRUNSRVRBUlkgT0YgQ09NTUVSQ0UiKSB+ICJERVBVVFkiLAogICAgVFJVRSB+IGNvbnRyaWJ1dG9yX29jY3VwYXRpb24gIAogICkpCgoKb3ZlcmFsbF90b3RhbHMgPC0gY2xlYW5fb2NjdXBhdGlvbiB8PiAKICBzdW1tYXJpemUoCiAgICB0b3RhbF9qb2JzID0gc3VtKG51bWJlcl9qb2JzLCBuYS5ybSA9IFRSVUUpLAogICAgdG90YWxfZG9uYXRpb25zID0gc3VtKHRvdGFsX2RvbmF0aW9ucywgbmEucm0gPSBUUlVFKQogICkKCgpjZW9fZGVwdXR5X3Byb3BvcnRpb25zIDwtIGNsZWFuX29jY3VwYXRpb24gfD4gCiAgZmlsdGVyKGNsZWFuZWRfampvYnMgJWluJSBjKCJDRU8iLCAiREVQVVRZIikpIHw+IAogIGdyb3VwX2J5KGNsZWFuZWRfampvYnMpIHw+IAogIHN1bW1hcml6ZSgKICAgIHRvdGFsX251bWJlcl9qb2JzID0gc3VtKG51bWJlcl9qb2JzLCBuYS5ybSA9IFRSVUUpLAogICAgdG90YWxfbnVtX2RvbmF0aW9ucyA9IHN1bShudW1fZG9uYXRpb25zLCBuYS5ybSA9IFRSVUUpLAogICAgdG90YWxfZG9uYXRpb25zID0gc3VtKHRvdGFsX2RvbmF0aW9ucywgbmEucm0gPSBUUlVFKQogICkgfD4gCiAgbXV0YXRlKAogICAgcHJvcF9udW1iZXJfam9icyA9IHJvdW5kKCh0b3RhbF9udW1iZXJfam9icyAvIG92ZXJhbGxfdG90YWxzJHRvdGFsX2pvYnMpICogMTAwLCAyKSwKICAgIHByb3BfdG90YWxfZG9uYXRpb25zID0gcm91bmQoKHRvdGFsX2RvbmF0aW9ucyAvIG92ZXJhbGxfdG90YWxzJHRvdGFsX2RvbmF0aW9ucykgKiAxMDAsIDIpCiAgKQoKCmNlb19kZXB1dHlfcHJvcG9ydGlvbnMKCmBgYAoKI0Fuc3dlciA0OiAKClRvIGFuc3dlciB0aGlzIHF1ZXN0aW9uLCB3ZSBwdXQgYSBjc3Ygb2Ygb2NjdXBhdGlvbnMgaW50byBPcGVuUmVmaW5lLiBXZSBvcmlnaW5hbGx5IHBsYW5uZWQgdG8gbGltaXQgdGhlIGRhdGEgc2V0LCBidXQgd2UgZm91bmQgdGhhdCB0aGVyZSB3ZXJlIG9ubHkgMSw5NjMgam9iIHRpdGxlcyBpbiB0aGUgZGF0YSBzZXQsIHdoaWNoIHNlZW1lZCBsaWtlIGEgcmVhc29uYWJsZSBudW1iZXIgdG8gcmVmaW5lIGRvd24gaW50byBhIHNtYWxsZXIgbGlzdCBvZiBqb2JzLiAKClRvIGRvIHRoaXMsIHdlIGdyb3VwZWQgY2VydGFpbiBqb2JzIGludG8gY2F0ZWdvcmllcyBsaWtlICJkaXJlY3RvciIgYW5kICJleGVjdXRpdmUiIC0tIHNvIGpvYiB0aXRsZXMgbGlrZSAic2FsZXMgZGlyZWN0b3IiIHdlbnQgaW50byB0aGUgImRpcmVjdG9yIiBjYXRlZ29yeS4gCgpXZSBjaG9zZSB0byBmb2N1cyBvbiBDRU9TIGFuZCBiZWdhbiBieSBwdWxsaW5nIGFuZCBtZXJnaW5nIGFsbCBvZiB0aGUgc2FtZSB0ZXJtcyBmb3IgQ0VPLiBUaGVyZSB3ZXJlIDIwIG9mIHRoZW0uIFdlIHRoZW4gZGVjaWRlZCB0byBjb21wYXJlIHRoYXQgdG8gZGVwdXRpZXMsIHdoaWNoIHdhcyBleHRyZW1lbHkgaW50ZXJlc3RpbmcgdG8gdXMgYmVjYXVzZSB0aGV5IGFyZSBnb3Zlcm5tZW50IGVtcGxveWVlcy4gQWNjb3JkaW5nIHRvIHJlc2VhcmNoLCB0aGV5IGFyZSBhbGxvd2VkIHRvIGRvbmF0ZS4gV2UgbWVyZ2VkIGFsbCBvZiB0aGUgbmFtZXMgd2l0aCBkZXB1dHkgdG9nZXRoZXIuIFRoZW4gd2UgY3JlYXRlZCBhIG5ldyBkYXRhc2V0IHdpdGggREVQVVRZIGFuZCBDRU8sIGJ1dCB0aGUgbnVtYmVycyBhcmUgZGlzcG9ycG9ydGlvbmF0ZSwgc28gd2UgbWFkZSB0aGVtIHByb3BvcnRpbmF0ZSBhcyBmb2xsb3dzOiAKcHJvcF9udW1iZXJfam9icwlQcm9wb3J0aW9uIG9mIGpvYnMgaW4gdGhlIGRhdGFzZXQgZm9yIGVhY2ggY2F0ZWdvcnksIHJlbGF0aXZlIHRvIHRoZSB0b3RhbCBudW1iZXIgb2Ygam9icy4KcHJvcF9udW1fZG9uYXRpb25zCVByb3BvcnRpb24gb2YgdGhlIG51bWJlciBvZiBkb25hdGlvbnMgbWFkZSwgcmVsYXRpdmUgdG8gdGhlIHRvdGFsIGRvbmF0aW9ucyBjb3VudC4KcHJvcF90b3RhbF9kb25hdGlvbnMJUHJvcG9ydGlvbiBvZiB0aGUgdG90YWwgZG9sbGFyIHZhbHVlIGRvbmF0ZWQsIHJlbGF0aXZlIHRvIHRoZSB0b3RhbCBkb25hdGlvbiBhbW91bnQuCgpPdXIgYW5hbHlzaXMgc2hvd2VkIHRoYXQgQ0VPcyBtYWtlIHVwIG9ubHkgMS44OCUgb2YgYWxsIGpvYnMgaW4gdGhlIGRhdGFzZXQsIGJ1dCB0aGV5IGFjY291bnQgZm9yIDMuNTklIG9mIHRoZSB0b3RhbCBkb25hdGlvbnMuIFRoaXMgbWVhbnMgdGhhdCB3aGlsZSB0aGVyZSBhcmVu4oCZdCBtYW55IENFT3MgY29tcGFyZWQgdG8gb3RoZXIgam9iIHRpdGxlcywgdGhleSBkb25hdGUgYSBsb3QgbW9yZSBtb25leSwgd2hpY2ggcmVmbGVjdHMgdGhlaXIgZmluYW5jaWFsIGluZmx1ZW5jZS4KCk9uIHRoZSBvdGhlciBoYW5kLCBERVBVVFlzLG1hbnkgb2Ygd2hvbSBhcmUgZ292ZXJubWVudCBlbXBsb3llZXMsIG1ha2UgdXAgIDAuMDglIG9mIGFsbCBqb2JzIGFuZCBjb250cmlidXRlIG9ubHkgMC4wNSUgb2YgdG90YWwgZG9uYXRpb25zLiBUaGlzIGlzIGEgbXVjaCBzbWFsbGVyIHByZXNlbmNlIGNvbXBhcmVkIHRvIENFT3MgYW5kIHNob3dzIHRoYXQgcHVibGljIHNlY3RvciBlbXBsb3llZXMgbGlrZSBERVBVVFlzIGRvbmF0ZSBmYXIgbGVzcyBvdmVyYWxsLgoKVGhpcyBpcyBpbXBvcnRhbnQgYmVjYXVzZSBpdCBoaWdobGlnaHRzIGEgY2xlYXIgZGlmZmVyZW5jZSBiZXR3ZWVuIHByaXZhdGUtc2VjdG9yIGxlYWRlcnNoaXAgcm9sZXMgYW5kIGdvdmVybm1lbnQgcG9zaXRpb25zIHdoZW4gaXQgY29tZXMgdG8gZG9uYXRpb25zLiBDRU9zLCB3aG8gb2Z0ZW4gZWFybiBoaWdoIHNhbGFyaWVzLCBzZWVtIHRvIGhhdmUgbXVjaCBtb3JlIGZpbmFuY2lhbCBwb3dlciB0byBtYWtlIGRvbmF0aW9ucy4gREVQVVRZcywgaW4gY29udHJhc3QsIGNvbnRyaWJ1dGUgZmFyIGxlc3MsIHdoaWNoIG1pZ2h0IHJlZmxlY3QgZGlmZmVyZW5jZXMgaW4gaW5jb21lIG9yIHJ1bGVzIGFib3V0IHBvbGl0aWNhbCBnaXZpbmcgZm9yIHB1YmxpYyBlbXBsb3llZXMuCgpXaGF0IHN0YW5kcyBvdXQgaXMgdGhhdCBkb25hdGlvbnMgYXJlbuKAmXQgc3ByZWFkIGV2ZW5seSBhY3Jvc3Mgam9iIHR5cGVz4oCUbW9zdCBvZiB0aGUgbW9uZXkgY29tZXMgZnJvbSBhIHNtYWxsIGdyb3VwIG9mIHBlb3BsZSBpbiBsZWFkZXJzaGlwIHBvc2l0aW9ucy4gVGhpcyByYWlzZXMgaW50ZXJlc3RpbmcgcXVlc3Rpb25zIGFib3V0IGluY29tZSwgaW5mbHVlbmNlLCBhbmQgaG93IGRvbmF0aW9ucyBzaGFwZSB0aGluZ3MgbGlrZSBwb2xpdGljYWwgY2FtcGFpZ25zIG9yIGNoYXJpdGFibGUgZWZmb3J0cy4KClRoaXMgaXMgbmV3c3dvcnRoeSBiZWNhdXNlIGl0IGhpZ2hsaWdodHMgaG93IGEgc21hbGwgZ3JvdXAgb2YgaGlnaC1pbmNvbWUgQ0VPcyBkaXNwcm9wb3J0aW9uYXRlbHkgZHJpdmVzIGRvbmF0aW9ucywgcmV2ZWFsaW5nIGVjb25vbWljIGRpc3Bhcml0aWVzIGFuZCB0aGUgb3V0c2l6ZWQgZmluYW5jaWFsIGluZmx1ZW5jZSBvZiBwcml2YXRlLXNlY3RvciBsZWFkZXJzLgoKCiNRdWVzdGlvbiA1OiBXaGF04oCZcyB0aGUgbWFrZXVwIG9mIGRvbmF0aW9ucyByZWNlaXZlZCBieSBIb2dhbiBhbmQgQWxzb2Jyb29rcz8gV2hhdCBwZXJjZW50YWdlIG9mIHRoZWlyIG92ZXJhbGwgZG9uYXRpb25zIHdlcmUgbGFyZ2UgYW1vdW50cyBvZiBtb25leSAodG8gYmUgZGVmaW5lZCwgYnV0ID4gJDEwMDAsIGZvciBleGFtcGxlKSB2cyBzbWFsbCBhbW91bnRzPwoKYGBge3J9CmhvZ2FuX2ZpbHRlcmVkX2RhdGEgPC0gZmluYWxfZGF0YSB8PgogIGZpbHRlcihjb21taXR0ZWVfbmFtZSAlaW4lIGMoIkhPR0FOIEZPUiBNQVJZTEFORCBJTkMuIikpCmxhcmdlX2RvbmF0aW9uX3RocmVzaG9sZCA8LSAxMDAwCgpob2dhbl9maWx0ZXJlZF9kYXRhIHw+IG11dGF0ZSggZG9uYXRpb25fY2F0ZWdvcnkgPSBpZmVsc2UoY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50ID4gbGFyZ2VfZG9uYXRpb25fdGhyZXNob2xkLCAiTGFyZ2UiLCAiU21hbGwiKSApCgpob2dhbl9jYXRlZ29yeV90b3RhbHMgPC0gaG9nYW5fZmlsdGVyZWRfZGF0YSB8PgogIG11dGF0ZShkb25hdGlvbl9jYXRlZ29yeSA9IGlmZWxzZShjb250cmlidXRpb25fcmVjZWlwdF9hbW91bnQgPiBsYXJnZV9kb25hdGlvbl90aHJlc2hvbGQsICJMYXJnZSIsICJTbWFsbCIpKSB8PgogIGdyb3VwX2J5KGRvbmF0aW9uX2NhdGVnb3J5KSB8PgogIHN1bW1hcmlzZSh0b3RhbF9hbW91bnQgPSBzdW0oY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50LCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKQoKaG9nYW5fY2F0ZWdvcnlfdG90YWxzICU+JSBtdXRhdGUoIHBlcmNlbnRhZ2UgPSB0b3RhbF9hbW91bnQgLyBzdW0odG90YWxfYW1vdW50KSAqIDEwMCApCgpob2dhbl9jYXRlZ29yeV90b3RhbHMKYGBgCgpgYGB7cn0KYWxzb2Jyb29rc19maWx0ZXJlZF9kYXRhIDwtIGZpbmFsX2RhdGEgfD4KICBmaWx0ZXIoY29tbWl0dGVlX25hbWUgJWluJSBjKCJBTFNPQlJPT0tTIEZPUiBTRU5BVEUiKSkKCmxhcmdlX2RvbmF0aW9uX3RocmVzaG9sZCA8LSAxMDAwCgphbHNvYnJvb2tzX2NhdGVnb3J5X3RvdGFscyA8LSBhbHNvYnJvb2tzX2ZpbHRlcmVkX2RhdGEgfD4KICBtdXRhdGUoZG9uYXRpb25fY2F0ZWdvcnkgPSBpZmVsc2UoY29udHJpYnV0aW9uX3JlY2VpcHRfYW1vdW50ID4gbGFyZ2VfZG9uYXRpb25fdGhyZXNob2xkLCAiTGFyZ2UiLCAiU21hbGwiKSkgfD4KICBncm91cF9ieShkb25hdGlvbl9jYXRlZ29yeSkgfD4KICBzdW1tYXJpc2UodG90YWxfYW1vdW50ID0gc3VtKGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICJkcm9wIikKCmFsc29icm9va3NfY2F0ZWdvcnlfdG90YWxzICAlPiUgbXV0YXRlKCBwZXJjZW50YWdlID0gdG90YWxfYW1vdW50IC8gc3VtKHRvdGFsX2Ftb3VudCkgKiAxMDAgKQoKYWxzb2Jyb29rc19jYXRlZ29yeV90b3RhbHMKYGBgCgoKYGBge3J9CmhvZ2FuX2ZpbHRlcmVkX2RhdGEgPC0gaG9nYW5fZmlsdGVyZWRfZGF0YSB8PiAKICBtdXRhdGUoY29udHJpYnV0b3JfemlwID0gc3Vic3RyKGFzLmNoYXJhY3Rlcihjb250cmlidXRvcl96aXApLCAxLCA1KSkKCmBgYAoKYGBge3J9CmhvZ2FuX3ppcHMgPC0gaG9nYW5fZmlsdGVyZWRfZGF0YSB8PgogIGdyb3VwX2J5KGNvbnRyaWJ1dG9yX3ppcCkgfD4KICBzdW1tYXJpc2UoY291bnQgPSBuKCkpCgp3cml0ZV9jc3YoaG9nYW5femlwcywgImhvZ2FuX3ppcHMuY3N2IikKYGBgCgpgYGB7cn0KYWxzb2Jyb29rc19maWx0ZXJlZF9kYXRhIDwtIGFsc29icm9va3NfZmlsdGVyZWRfZGF0YSB8PiAKICBtdXRhdGUoY29udHJpYnV0b3JfemlwID0gc3Vic3RyKGFzLmNoYXJhY3Rlcihjb250cmlidXRvcl96aXApLCAxLCA1KSkKCmBgYAoKYGBge3J9CmFsc29icm9va3NfemlwcyA8LSBhbHNvYnJvb2tzX2ZpbHRlcmVkX2RhdGEgfD4KICBncm91cF9ieShjb250cmlidXRvcl96aXApIHw+CiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKQoKd3JpdGVfY3N2KGFsc29icm9va3NfemlwcywgImFsc29icm9va3Nfemlwcy5jc3YiKQpgYGAKCmBgYHtyfQpob2dhbl9sYXJnZV9kYXRhIDwtIGhvZ2FuX2ZpbHRlcmVkX2RhdGEgfD4gCiAgbXV0YXRlKGNvbnRyaWJ1dG9yX3ppcCA9IHN1YnN0cihhcy5jaGFyYWN0ZXIoY29udHJpYnV0b3JfemlwKSwgMSwgNSkpIHw+IAogIGZpbHRlcihjb250cmlidXRpb25fcmVjZWlwdF9hbW91bnQgPiAxMDAwKSB8PgogIGdyb3VwX2J5KGNvbnRyaWJ1dG9yX3ppcCkgfD4KICBzdW1tYXJpc2UoY291bnQgPSBuKCkpCndyaXRlX2Nzdihob2dhbl9sYXJnZV9kYXRhLCAiaG9nYW5fbGFyZ2UuY3N2IikKYGBgCgpgYGB7cn0KYWxzb2Jyb29rc19sYXJnZV9kYXRhIDwtIGFsc29icm9va3NfZmlsdGVyZWRfZGF0YSB8PiAKICBtdXRhdGUoY29udHJpYnV0b3JfemlwID0gc3Vic3RyKGFzLmNoYXJhY3Rlcihjb250cmlidXRvcl96aXApLCAxLCA1KSkgfD4gCiAgZmlsdGVyKGNvbnRyaWJ1dGlvbl9yZWNlaXB0X2Ftb3VudCA+IDEwMDApIHw+CiAgZ3JvdXBfYnkoY29udHJpYnV0b3JfemlwKSB8PgogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkKd3JpdGVfY3N2KGFsc29icm9va3NfbGFyZ2VfZGF0YSwgImFsc29icm9va3NfbGFyZ2UuY3N2IikKYGBgCgpBNTogSGVyZSB3ZSBzZWUgdGhhdCBIb2dhbiByZWNlaXZlcyBzaWduZmljYW50bHkgbW9yZSBtb25leSBpbiBnZW5lcmFsIGluIGNvbXBhcmlzb24gdG8gQWxzb2Jyb29rcy4gQWRkaXRpb25hbGx5LCBIb2dhbiByZWNlaXZlcyBtYW55IG1vcmUgbGFyZ2UgZG9uYXRpb25zIChpbiBleGNlc3Mgb2YgbWlsbGlvbnMpIGluIGNvbXBhcmlzb24gdG8gQWxzb2Jyb29rcy4gV2hlcmVhcywgdGhlIHNtYWxsIGRvbmF0aW9ucyBhcmUgYXJvdW5kIDYwMCwwMDAgbW9yZS4gVGhpcyBzaG93cyB0aGF0IGVpdGhlciBIb2dhbiBoYXMgYSBsYXJnZXIgImZhbiBiYXNlIiBvZiBwZW9wbGUgd2hvIGRvbmF0ZSB0byBoaW0gb3IgcGVyaGFwcyBoaXMgZWxlY3RvcmF0ZSBpcyBqdXN0IHdlYWx0aGllci4gQWRkaXRpb25hbGx5LGl0IHdvdWxkIGJlIGludGVyZXN0aW5nIHRvIG5vdGUgd2hldGhlciBIb2dhbiBoYXMgYSBoaWdoZXIgYW1vdW50IG9mIGRvbmF0aW9ucyBiZWNhdXNlIGhlIHdhcyBrbm93biBiZWZvcmUuIAoKV2UgdGhlbiBsb29rZWQgYXQgd2hlcmUgdGhlc2UgZG9uYXRpb25zIHdlcmUgZnJvbS4gRm9yIEhvZ2FuLCBoaXMgbW9zdCBkb25hdGlvbnMgY2FtZSBmcm9tIEFubmFwb2xpcyAtLS0gaGlzIGZvcm1lciByZXNpZGVuY2UgYW5kIHdoZXJlIHRoZSBzdGF0ZSBsZWdpc2xhdHVyZSBpcyBsb2NhdGVkLiBIaXMgc2Vjb25kIG1vc3QgZG9uYXRpb25zIGNhbWUgZnJvbSBQb3RvbWFjLCB0aGUgemlwIGNvZGUgd2l0aCB0aGUgaGlnaGVzdCBtZWRpYW4gaG91c2Vob2xkIGluY29tZSBpbiBNYXJ5bGFuZC4gSG93ZXZlciwgMTQgZGlmZmVyZW50IHppcCBjb2RlcyBkb25hdGVkIG1vcmUgdG8gQWxzb2Jyb29rcyB0aGFuIEFubmFwb2xpcyBkaWQgZm9yIEhvZ2FuLiBUaGlzIHNob3dlZCBIb2dhbiB0aHJpdmVkIG9mZiBvZiBsYXJnZSBkb25hdGlvbnMgaW4gYXJlYXMgdGhhdCBBbHNvYnJvb2tzIGRpZCByZWFjaC4KCldlIHRlc3RlZCB0aGlzIHVzaW5nIGNobG9yb3BsZXRoIG1hcHMgdG8gc2hvdyB0aGUgemlwIGNvZGVzIHdoZXJlIHRoZSB0d28gcmVjZWl2ZWQgbGFyZ2UgZG9uYXRpb25zLiBUaGUgbWFwIHNob3dlZCBhIGxvdCBvZiBhcmVhcyBpbiBub3J0aGVybiBNYXJ5bGFuZCBoZSBjYXBpdGFsaXplZCB3aXRoIHRob3NlIGRvbmF0aW9ucyB3aGVyZSBBbHNvYnJvb2tzIGRpZCBub3QgcmVjaWV2ZSBhbnkuICAKClRoZXJlIHdlcmUgYSBmZXcgemlwIGNvZGVzIHdoaWNoIGRpZCBub3QgcmVnaXN0ZXIgb24gRGF0YVdyYXBwZXIgd2hlbiBtYWtpbmcgdGhlc2UgZ3JhcGhzLCBidXQgdGhleSBkaWQgbm90IGhhdmUgbW9yZSB0aGFuIGZpdmUgZG9uYXRpb25zLCBzbyB3ZSBkaWQgbm90IHRoaW5rIHRoYXQgaXQgdWx0aW1hdGVseSBhZmZlY3RlZCBkZXRlcm1pbmluZyB3aGVyZSB0aGUgaG90IGFyZWFzIHdlcmUgZm9yIHRoZSB0d28gcmVjZWl2aW5nIHRoZWlyIGRvbmF0aW9ucy4gCgpNYXAgb2YgTGFycnkgSG9nYW4ncyBkb25hdGlvbnMgYnkgemlwY29kZTogaHR0cHM6Ly93d3cuZGF0YXdyYXBwZXIuZGUvXy81TEIzVC8KCk1hcCBvZiBBbmdlbGEgQWxzb2Jyb29rcycgZG9uYXRpb25zIGJ5IHppcGNvZGU6IApodHRwczovL3d3dy5kYXRhd3JhcHBlci5kZS9fL0NodEFyLyAKCk1hcCBvZiBBbmdlbGEgQWxzb2Jyb29rcycgbGFyZ2UgZG9uYXRpb25zIGJ5IHppcGNvZGU6Cmh0dHBzOi8vd3d3LmRhdGF3cmFwcGVyLmRlL18vQkV1dlkvIAoKTWFwIG9mIExhcnJ5IEhvZ2FuJ3MgbGFyZ2UgZG9uYXRpb25zIGJ5IHppcGNvZGU6IApodHRwczovL3d3dy5kYXRhd3JhcHBlci5kZS9fLzZLVEYzLwoKCgoKCgoKCgoK